小编这次要给大家分享的是解决Java返回可变引用对象问题,文章内容丰富,感兴趣的小伙伴可以来了解一下,希望大家阅读完这篇文章之后能够有所收获。
<强> 1。问题强>
/* * *输出:Mon 10:54:10 CST 2010年4月26日 *我的10:54:10 CST 2010年4月26日 */公共静态void main (String [] args) { 示例测试=new示例(新日期()); d=test.getDate日期(); 双tenYearsInMillisSeconds=10 * 365.25 * 24 * 3600 * 1000; d.setTime(长)(d.getTime () - tenYearsInMillisSeconds)); System.out.println (d); System.out.println (test.getDate ()); } 公开课例{ 私人约会日期; 公共的例子(日期日期){ 这一点。日期=日期; } 公众获取日期日期(){ 返回日期; } }
<代码> 代码>日期类破坏了<代码> 代码示例的封装,导致修改实例<代码> d> 代码时影响了<代码> 代码>的测试值,原因是<代码> 代码>日期类生成的对象是可变的。
<强> 2。对象与对象变量强>
日期生日=new日期(); 日期截止日期=生日;
这两个变量引用同一个对象(请参见图4 - 4)。
但一个对象变量并没有实际包含一个对象,而仅仅引用一个对象。
在Java中,任何对象变量的值都是对存储在另外一个地方的一个对象的引用。<代码> 代码>新操作符的返回值也是一个引用。
<代码>日期生日=new日期();> 代码可以理解为<代码>新日期()代码>构造了一个<代码> 代码>日期类型的对象,并且它的值是对新创建对象的引用。这个引用存储在变量<代码> 代码>中生日。
Java对象变量与c++的引用并不同
可以将Java的对象变量看作c++的对象指针。例如,
日期生日;//Java
实际上,等同于
日期*生日;//c++
所有的Java对象都存储在堆中。当一个对象包含另一个对象变量时,这个变量依然
包含着指向另一个堆对象的指针。
<强> 3。更改器方法与访问器方法强>
上文还是没有解释清楚为什么<代码> 代码>日期类的对象是可变对象,原因在这。
假设在上文中<代码> >代码示例类中使用Java中与<代码> 代码>日期类相近的<代码> LocalDate> 代码类便不会出现上述情况,测试可以自己去尝试。
原因在于假设使用<代码> LocalDate> 代码类中的<代码> plusDays 代码>方法来修改对象变量,它会生成一个新的<代码> LocalDate> 代码对象,然后把这个新对象赋值给调用者,原来的对象不做任何改动。
此类只访问对象而不修改对象的方法有时称为访问器方法( 访问器方法)
而像<代码> 代码>日期类中的凝固时间<代码> 代码>方法会使得原对象的状态发生改变,此类称为更改器方法( mutator方法)
<强> 4。解决方法强>
如果需要返回一个可变数据域的拷贝,就应该使用克隆。这样会创建一个当前对象的副本,而不会对当前对象造成影响。<代码类="语言java "> 代码>
{公共类示例 私人约会日期; 公共的例子(日期日期){ 这一点。日期=日期; } 公众获取日期日期(){ 返回(日期)date.clone (); } }
<强> 5。不可变类强>
5.1什么是不可变类
不可变类指当类被实例化后,该类的成员变量均不可被改变。
如JDK内部自带的很多不可变类<代码> 代码,浮点数值用<代码> 代码>,<代码>布尔代码>和<代码> 代码>等字符串。
5.2优缺点优点:
1。线程安全
2。易于构造,使用和测试
3。可以被自由地共享缺点:对于每一个不同的值都需要对应一个单独的对象5.3如何实现不可变类类需要用最后<代码> 代码>修饰,保证类不能被继承所有成员变量需要私人代码> <代码>修饰,保证成员变量不能直接被访问类中不允许提供<代码> setter代码>方法,保证成员变量不会被改变在<代码> getter 代码>方法中不能返回对象本身,返回对象的拷贝
看完这篇关于解决Java返回可变引用对象问题的文章,如果觉得文章内容写得不错的话,可以把它分享出去给更多人看到。