(文章部分摘自《Java编程思想》)
别名现象
1.对象赋值的中别名现象
2.方法调用中的别名问题
在开始介绍别名现象之前,首先要说造成别名现象的原因:
在基本类型的赋值的时候,基本数据类型就会存储这个数据的实际数值,在为其赋值的时候或者复制该值到另一个基本类型的时候,就是将该实际数值复制并且赋值给另一个基本类型;但是在为一个“对象”赋值的时候,就不一样了,对象里实际上保存的是对象的引用。此时,如果将一个对象的值赋值给另一个对象,实际上就是把该对象的“引用”赋给了另一个对象。这时,实际上这两个对象,指向的是同一个内容。
在了解了赋值时所产生的问题后,我们再来讨论别名现象。
1.对象赋值中的别名现象:
我们先来看一段代码:
package 类测试和学习;
class struct{
int content;
}
public class TestOfEquals {
public static void main(String[] args) {
struct t1 = new struct();
struct t2 = new struct();
t1.content = 10;
t2.content = 20;
System.out.println("*********---Step 1---*********");
System.out.println("t1.content:"+t1.content);
System.out.println("t2.content:"+t2.content);
System.out.println("*********---Step 2---*********");
t1.content = t2.content; //对t1和t2中的基础数据进行操作
System.out.println("t1.content:"+t1.content);
System.out.println("t2.content:"+t2.content);
System.out.println("*********---Step 3---*********");
t1.content = 30; //给t1.content赋值30
System.out.println("t1.content:"+t1.content);
System.out.println("t2.content:"+t2.content);
System.out.println("*********---Step 4---*********");
t1 = t2; //对t1和t2两个对象的操作
System.out.println("t1.content:"+t1.content);
System.out.println("t2.content:"+t2.content);
System.out.println("*********---Step 5---*********");
t1.content=50; //给t1.content赋值
System.out.println("t1.content:"+t1.content);
System.out.println("t2.content:"+t2.content);
}
}
这段代码的输出结果:
*********---Step 1---*********
t1.content:10
t2.content:20
*********---Step 2---*********
t1.content:20
t2.content:20
*********---Step 3---*********
t1.content:30
t2.content:20
*********---Step 4---*********
t1.content:20
t2.content:20
*********---Step 5---*********
t1.content:50
t2.content:50
分析一下这个程序和结果:
struct类中含有一个int类型的变量,我们对其进行赋值,就是对基本数据类型的赋值。在main函数中,我们new了两个新的对象t1和t2。目前,我们程序中就出现了两种数据:基本数据类型(t1.content和t2.content)和对象(t1和t2)。
step 1 时,我们对t1.content进行了赋值操作,这样保持了数据的独立;所以即使在t1.content进行了重新赋值的操作,也不会影响到t2.content。
但是,对于t1=t2的操作,我们实际上是对引用的赋值,也就是实际上让t1的引用和t2指向了同一个对象。当我们再次修改t1.content的时候(Step 5),也同时改变了t2.content。在对t1的引用赋值时,原本t1的引用会被覆盖掉,最终被“垃圾回收机制”所回收掉。
2.方法调用中的别名问题:
同样的 ,我们根据一段代码来了解一下在方法调用中因为别名现象产生的问题:
package 类测试和学习;
class charin{
char r ;
}
public class TestOfEquals {
static void f(charin y) {
System.out.println("传递之后的y.r:"+y.r);
y.r = 'z';
}
public static void main(String[] args) {
charin x = new charin();
x.r='A';
System.out.println("*********---Step 1---*********");
System.out.println(x.r);
System.out.println("*********---Step 2---*********");
f(x);
System.out.println(x.r);
}
}
这段代码的结果是这样的:
*********---Step 1---*********
A
*********---Step 2---*********
传递之后的y.r:A
z
在我们调用f(y)这个方法的时候,将x的引用传递给了y(y=x),y.z=‘z’,实际上改变的对象,就是传递进来的对象。
新人新思,必有所误,
还望雅涵,有异评罢。