Java赋值操作需要注意的地方

摘录自 << Thinking In Java >>

赋值使用操作符" == “.它的意思是"取右边的的值(即右值),把他复制给左边(即左值)”.右值可以是任何常数,变量或者表达式(只要它能生成一个值就行).但左值必须是一个明确的已命名的变量.也就是说,必须有一个物理空间可以存储等号右边的值.

举例来说,可将一个常数赋给一个变量:
a = 4;
但是不能把任何东西赋给一个常数,常数不能作为左值(比如不能说4 = a;);

对基本数据类型的赋值是很简单的.基本类型存储了实际的数值,而并非指向一个对象的引用,所以再为其赋值的时候,是直接将一个地方的内容直接复制到了另一个地方.例如:对基本数据类型的使用 a = b;,那么b的内容就复制给了a.若接着又修改了a,而b根本不会受到这种修改的影响.

但是在位"对象"赋值的时候,情况却发生了变化.对一个对象进行操作的时候,我们真正操作的是对对象的引用.所以倘若"将一个对象赋值给另一个对象",实际是将"引用"从一个地方复制到了另一个地方.这就意味者倘若对对象使用"c=d;"那么c和d都指向原本只有d指向的那个对象.

举个例子:

public class TestMain {

	public static void main(String[] args) throws InterruptedException {
		TestTank t1 = new TestTank();
		TestTank t2 = new TestTank();
		t1.level = 9;
		t2.level = 47;
		System.out.println("1: t1.level: " + t1.level + ", t2.level: " + t2.level);
		t1 = t2;
		System.out.println("2: t1.level: " + t1.level + ", t2.level: " + t2.level);
		t1.level = 27;
		System.out.println("3: t1.level: " + t1.level + ", t2.level: " + t2.level);
	}
}

class TestTank {
	int level;
}

结果输出:
1: t1.level: 9, t2.level: 47
2: t1.level: 47, t2.level: 47
3: t1.level: 27, t2.level: 27

TestTank类非常简单,它的两个实例( t1和t2)是在 main()里创建的。对每个 TestTank 类对象的 level 域都赋予了一个不同的值,然后,将t2赋给 t1 ,接着又修改了t1。

在许多编程语言中,我们可能会期望 t1 和 t2 总是相互独立的。但由于赋值操作的是一个对象的引用,所以修改 t1 的同时也改变了 t2 !这是由于 t1 和 t2 包含的是相同的引用,它们指向相同的对象。(原本t1包含的对对象的引用,是指向一个值为 9 的对象。在对 t1 赋值的时候,这个引用被覆盖,也就是丢失了;而那个不再被引用的对象会由“垃圾回收器”自动清理)这种特殊的现象通常称作“别名现象”,是 Java 操作对象的一种基本方式。

在这个例子中,如果想避免别名问题应该怎么办呢?可以这样写:
t1.level = = t2.level;
这样便可以保持两个对象彼此独立,而不是将 t1和t2绑定到相同的对象。但你很快就会意识到,直接操作对象内的域容易导致混乱,并且,违背了良好的面向对象程序设计的原则。

这可不是一个小问题,所以从现在开始大家就应该留意,为对象赋值可能会产生意想不到的结果。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值