对一个对象进行操作的时候,我们真正操作的是对对象的引用,所以,倘若“将一个对象赋值给另一个对象”,实际是将”引用”从一个地方赋值到另一个地方,这意味着假若对对象使用c=d,那么c和d都指向原本只有d指向的那个对象。
class Tank {
int level;
}
/**
* @Author ZhangGJ
* @Date 2020/11/14 06:55
*/
public class Assigment {
public static void main(String[] args) {
Tank t1 = new Tank();
Tank t2 = new Tank();
t1.level = 9;
t2.level = 47;
System.out.println("1: t1.level: " + t1.level + ", t2.level: " + t2.level);
/**
* 由于赋予的只是对象的引用,改变 t1 也就改变了 t2。 这是因为 t1 和 t2 此时指向的是堆中同一个对象。(t1
* 原始对象的引用在 t2 赋值给其时丢失,它引用的对象会在垃圾回收时被清理)
* 这种现象通常称为别名(aliasing)
*/
t1 = t2;
System.out.println("2: t1.level: " + t1.level + ", t2.level: " + t2.level);
/**
* 修改t1的同时也就改变了t2,这是由于t1和t2包含的是相同的引用,它们指向相同的对象
*/
t1.level = 27;
System.out.println("3: t1.level: " + t1.level + ", t2.level: " + t2.level);
}
}
result:
1: t1.level: 9, t2.level: 47
2: t1.level: 47, t2.level: 47
3: t1.level: 27, t2.level: 27
如何避免别名问题?
t1.level = t2.level
方法调用中的别名问题
class Letter {
char c;
}
/**
* @Author ZhangGJ
* @Date 2020/11/14 07:03
*/
public class PassObject {
static void f(Letter y) {
y.c = 'z';
}
public static void main(String[] args) {
Letter x = new Letter();
x.c = 'a';
System.out.println("1: x.c: " + x.c);
f(x);
System.out.println("2: x.c: " + x.c);
}
}
result:
1: x.c: a
2: x.c: z