对象和对象引用的对应关系:
(1)一个对象引用可以指向0个或1个对象(一根绳子可以不系汽球,也可以系一个汽球);
(2)一个对象可以有N个引用指向它(可以有N条绳子系住一个汽球)。
public static void main(String[] args) { Test test1 = new Test(); Test test2 = new Test(); test1 = test2;//内存泄漏,test1 new出来的对象没有引用指向,称为gc回收的对象 }
从存储空间上来说,对象一般存储在堆中,而引用存储在栈中。
值传递:如果传入方法的是基本类型,你就得到此基本类型的一份拷贝。如果是传递引用,就得到引用的拷贝。
public class Test { //基本类型的参数传递 public static void testBasicType(int m) { System.out.println("m=" + m);//m=50 m = 100; System.out.println("m=" + m);//m=100 } //改变了原来的sMain,因为s和sMain其实是指向同一地址 public static void add(StringBuffer s) { s.append("_add"); } //没改变原来的sMain,因为s和sMain指向了不同地址, public static void changeRef(StringBuffer s) { s = new StringBuffer("Java"); } //String类具有不变性,这里虽然只是+"111",但对于String来说,其实跟new是一回事,所以原s没变。 public static void changeS(String s) { s = s + "111"; } 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 String s = new String("test"); changeS(s); System.out.println("s:" + s);//s:test,注意以下String类的特殊性 } }
总结:
A a = new A();//a是引用,new A()是对象
引用存的是地址,不是对象本身。所以如果传参是引用的话,在函数中,如果对于拷贝引用,没有改变其地址,则对拷贝引用的改变,就是对原参数的改变;如果对拷贝引用改变了地址,比如new了一个新对象,则其改变就不再是对原参数的改变了,原参数不会有任何变化,当然如果在这种情况下,还想对原参数产生影响,可以将这个拷贝引用return回去即可。