Java中有关等号的一些思考

  从学习C语言开发到学习Java开发,难免会因为两种不同性质的语言的不同行为而产生一些迷惑。比如对于“=”,两种语言的解读方式在某些层面是不一样的,这往往会给初学者带来一些疑惑。加之Java面向对象编程的特性和C语言的面向过程编程有很大不同,就更容易产生一些有趣的思考和问题。

  考察如下代码:这个简单的Java程序定义了一个简单的水果类,包含属性“水果名称”和“价格”。在主程序中定义了一个水果类的列表,并加入了三个初始元素。接下来使用迭代器对列表进行遍历,并且每次迭代过程,都新定义了一个fruit变量,并使用it.next()方法将列表元素赋值给它。之后修改这个fruit变量的值。最后,终端会输出修改变量前和修改变量后的列表首项内容。

public class TestReference {
	
	public static void main(String[] args) throws IOException{
		ArrayList<fruit> fruitList = new ArrayList<fruit>();
		fruitList.add(new fruit("apple",10));
		fruitList.add(new fruit("banana",20));
		fruitList.add(new fruit("pear",15));
		System.out.println(fruitList.get(0).name+"  "+fruitList.get(0).price);
		Iterator<fruit> it = fruitList.iterator();
		while(it.hasNext()) {
			fruit Case = it.next();
			Case.price+=100;
		}
		System.out.println(fruitList.get(0).name+"  "+fruitList.get(0).price);
	}
}

class fruit{
	String name;
	long price;
	public fruit(String name, long price) {
		this.name = name;
		this.price = price;
	}
}

  这个程序在终端的输出如下所示:

按照C语言的认识,在循环体中的变量只是被赋值为列表的某个元素,两者之间应该是相互独立的,可是为什么修改它,列表中的元素也发生了改变呢?

对这段代码的描述其实就出现了问题: “新定义了一个fruit变量,并使用it.next()方法将列表元素赋值给它”,这样的理解是不正确的,应该是创建了一个fruit对象,并且引用了列表中的某个对象,且引用类型是强引用。

在Java中,在对象(obj)之间使用等号,完全不是按照C语言解读的“赋值”,而是“引用”。Java中的确存在着与C语言中类似的赋值操作,对一个变量来说,如果为它创建的是基本数据类型(数值型、布尔型、字符型),那么其与C语言的赋值操作基本一致。但是如果其创建的是引用数据类型(类、接口、字符串等),那么此时变量相当于引用了这个数据类型,类似C语言中的“获得了这个数据类型的地址”,此时对变量进行操作,就相当于直接对这个地址下存储的信息进行操作,所以可以直接通过一个变量来改变引用数据类型的各种信息。

这种设计方式使得“=”有两种解读,方便了编程。但是这也带来了一个隐患:当多个变量引用了同一个引用数据类型时,对一个变量进行操作,其操作效果会直接反映到其它变量上。这有可能造成隐蔽而致命的错误。

用“地址”的思想也很好理解为什么会发生这种问题。为了预防这种隐患,我们可以把引用数据类型设计成immutable的,亦即“想要修改这个类的任何信息,除了新建一个对象外,别无他法”,落实到具体实现上,用类举例,则可以是:(1)类的所有属性都是私有的,这保证了无法用外界操作改变类的任何属性。(2)类内不提供任何修改属性的方法,也不会返回这个类的属性(实际上私属性私有就保证了属性不会泄露)。在这种限制下,很容易发现,引用这个对象后将无法对这个对象进行任何修改,如果想要“改变”它,只能重新创建一个对象,包含修改后的属性信息。这就避免了内存泄漏的错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值