"注意不要编写返回引用可变对象的访问器方法".因为会破坏类的封装性,引用的内容可能会被改变,产生业务逻辑上的错误.
什么是可变对象?
先要搞清楚java中值传递和引用传递的问题,总结如下:
1.对象就是传引用
2.原始类型就是传值
3.String,Integer, Double等immutable类型因为没有提供自身修改的函数,每次操作都是新生成一个对象,所以要特殊对待。可以认为是传值。
Integer 和 String 一样。保存value的类变量是Final属性,无法被修改,只能被重新赋值/生成新的对象。 当Integer 做为方法参数传递进方法内时,对其的赋值都会导致 原Integer 的引用被 指向了方法内的栈地址,失去了对原类变量地址的指向。对赋值后的Integer对象做得任何操作,都不会影响原来对象。
所以,可变对象即immutable类型外的一般对象.[immutable类:如果类中的每个方法否不会改变其对象,这种类就是不可变的类.]
如果需要返回一个可变对象的引用,首先对它克隆,使用.clone
,如return hireDay.clone();
,会生成另一个内存位置上的对象副本.
很多人对"java程序设计语言总是采用按值调用"这句话与引用传递产生误会,认为矛盾,其实不矛盾,引用传递时,方法调用的是对象的拷贝值,也是对类对象的引用,当方法调用结束时,拷贝值不再使用,方法执行过程中通过拷贝值修改的对象值被改变.
package com.ghw.test;
import java.util.Date;
/**
* java core中提到不要编写返回引用对象的访问器方法,此处对此演示
* 这里user.getTime返回的是time这个Date对象的引用,因此d调用setTime
* 修改的就是time这个对象。
*/
public class ReturnValueTest {
public static void main(String[] args) {
User user = new User();
Date d = user.getTime();
System.out.println(d); //Fri Aug 03 17:51:50 CST 2018
d.setTime(1);
System.out.println(user.getTime()); //Thu Jan 01 08:00:00 CST 1970
}
}
class User {
private Date time = new Date();
public Date getTime() {
return time; //可以在这里添加clone,return (Date) time.clone();
}
}
package com.ghw.test;
/**
* java core中提到类中的方法可以访问所属类的私有特性(属性或方法)
*/
public class ReturnValueTest {
public static void main(String[] args) {
User user1 = new User();
user1.hello();
}
}
class User {
public void hello() {
helloa();
}
private void helloa() {
System.out.println("helloa");
}
}