引用数据类型都是占用4个字节,表示对象的地址。
创建对象的步骤
People one = new People();
这条语句的动作称为创建一个对象,它包含了四个动作:
- 左侧的People one在栈中创建了一个名字为one的People类的引用变量。
- 右边的new People,是以People类为模板,在堆空间中创建一个People类对象
- 结尾的(),在对象创建后,立刻调用People类的构造函数,对刚生成的对象初始化。
- “=”操作符使对象引用 指向 刚创建的People对象。也可以说把把对象地址给了变量one。
步骤2,3可以看成一个整体,都属于JVM运行期中的“初始化”步骤
可以将上面的话拆成两句,效果一样:
People one;
one = new People();
如果只执行了第一条语句,还没执行第二条,此时创建的引用变量one还没指向任何一个对象,它的值是null。
引用的传递
People one = new People("张三");
People two = new People("李四");
one = two;
按上面的逻辑,引用one先指向对象“张三”,然后又指向了引用two指向的“李四”,所以最后one和two都指向对象“李四”,之前的对象“张三”由于不再被任何引用所指向,变成了垃圾回收机制的目标,至于什么时候被回收,那要看垃圾回收机制的心情了。【不是被立即回收的】
更改对象内容
People one = new People("张三");
People two = one;
one.setName("李四") // 更改one对象中的内容
引用的转移,此时修改one对象中的内容,无论打印one的名字还是two的名字,都是李四,不再是张三;如果修改two对象中的内容,同理,因为他们指向同一块内存区域。
如果把自定义对象Person换成数组对象,更改其中的某一位,也是这个效果。但是不能用Sting对象来测试这样的修改,因为它用final修饰不可更改,所有的操作都会创建新对象。
如果把自定义对象Person换成String,使用append方法,也是这个效果。
深拷贝和浅拷贝
- 浅拷贝只是复制了对象的引用地址,两个对象指向同一个内存地址,所以修改其中任意的值,另一个值都会随之变化
- 深拷贝是将对象复制过来,两个对象修改其中任意的值另一个值不会改变
作为对比,最后说一下基本数据类型
int a = 1;
int b = a;
a = 2;
System.out.println(a); // 2
System.out.println(b); // 1
int c=1
基本数据类型的变量和值都放在栈中,赋值(=号)就相当于拷贝了一份值,拷贝的值另开辟空间存放,不和对象那样可以被两个引用所指向,所以说,第2句,会使a=1 与 b=1 在栈中位于不同的空间,所以第3句修改a的值不会影响b。
第4句,会再开辟一块空间存 c=1 ,不会出现指向a的情况。
用一个例子说明:
第一句代码:
方法体里声明的基本数据类型在栈内存里,我们画一下
继续执行以下代码
对于基本数据类型来说,赋值(=号)就相当于拷贝了一份值,把int1的值100,拷贝给int2,继续画图
int1=500,直接修改int1的值为500,表现如下图
分别打印int1,int2的值,分别是500,100。
alexyyek.github.io/2014/12/29/… zhuanlan.zhihu.com/p/28654272