java中除了基本类型的变量是赋值操作,其他类型的赋值都是引用。
比如
public static void Test() {
ListNode a=new ListNode(1);
ListNode b = new ListNode(2);
a=b;
a.val=100;
System.out.println(b.val);
}
输出结果为100,说明a与b指向了同一个地址。
上述代码中,a指向了b的对象,a原来的对象会成为垃圾回收机制的处理对象,等待垃圾回收机制回收。
下面详细说明一下java中对象的引用。
设有一个类,定义为
public class Student
{
private int id;
private String name;
}
用这个类来创建对象
Student student1=new Student();
上面这个动作可以分解为
1)new Student(),创建一个对象,并利用构造函数对其进行初始化。
2)左边的Student student创建了一个Student类的引用变量。
3)=使建立的引用变量指向了创建的对象。
等价于
Student student;
student=new Student();
这也就解释了为什么当创建一个student2时
Student student2=student1
与student1指向的是同一个对象。
我们可以得到结论:
1)一个对象引用可以指向0个或1个对象
2)一个对象可以被N个引用指向
从存储空间上来说,引用和对象是独立的,对象一般存储在堆中, 引用一般存储在处理速度更快的堆栈中
java传参问题:
java只有一种参数传递方式——按值传递,java中传递任何东西都是传值。
如果传入的是基本类型,就得到基本类型的一份拷贝,如果传入的是引用,就得到引用的一份拷贝
public class ObjectRef {
//基本类型的参数传递
public static void testBasicType(int m) {
System.out.println("m=" + m);//m=50
m = 100;
System.out.println("m=" + m);//m=100
}
//参数为对象,不改变引用的值
public static void add(StringBuffer s) {
s.append("_add");
}
//参数为对象,改变引用的值
public static void changeRef(StringBuffer s) {
s = new StringBuffer("Java");
}
public static void main(String[] args) {
int i = 50;
testBasicType(i);
System.out.println(i);//i=50
StringBuffer sMain = new StringBuffer("init");
System.out.println("sMain=" + sMain.toString());//sMain=init
add(sMain);
System.out.println("sMain=" + sMain.toString());//sMain=init_add
changeRef(sMain);
System.out.println("sMain=" + sMain.toString());//sMain=init_add
}
}
以上程序的输出结果显示,testBasicType方法的参数是基本类型,尽管参数m的值发生改变,但并不影响i。
add方法的参数是一个对象,当把sMain传给参数s时,s得到的是sMain的拷贝,所以s和sMain指向同一个对象,因此,使用s操作影响的其实就是sMain指向的对象,故调用add方法后,sMain指向的对象的内容发生了改变。
在changeRef方法中,参数也是对象,当把sMain传给参数s时,s得到的是sMain的拷贝,但与add方法不同的是,在方法体内改变了s指向的对象(也就是s指向了别的对象,牵着气球的绳子换气球了),给s重新赋值后,s与sMain已经毫无关联,它和sMain指向了不同的对象,所以不管对s做什么操作,都不会影响sMain指向的对象,故调用changeRef方法前后sMain指向的对象内容并未发生改变。