Java中关于返回引用可变对象常见问题剖析
来源:互联网 发布:淘宝网服务中心 编辑:程序博客网 时间:2024/06/05 14:17
前言
在工程中,我们创建了一个类,经常包含一些可变类的对象实例,当我们需要提取这些数据的时候,需要格外注意,否则会出一些意料之外的问题
正文
名词解释
可变对象:类中有方法可以改变其对象实例域(数据域)的类
举例
假设我们有一个example类,其中为Date类创建了一个实体birthday,在外部需要知道某个example类实例的birthday值时,会使用到getBirthday()方法,通常我们的getBirthday()方法会写成如下的样子:
class Example{ private Date birthday; ... public Date getBirthday{ return birthday; } ...}
这样的写法,会破坏example类的封装性,因为当外部调用了getBirthday()这个方法后,生成了另一个对于birthday所引用对象的引用,在新的引用中调用Date类中的方法,同样会改变当前实例中birthday的值,例如如下代码:
Example e = new Example(....);Date d = e.getBirthday();double tenYearsInMilliSeconds = 10 * 365.25 * 24 * 60 * 60 * 1000;d.setTime(d.getTime() - (long) tenYearsInMilliSeconds);
这样的代码,会使得再次调用e.getBirthday()后,得到的值是修改后的值。
原因
上述例子中,d和e.birthday引用了同一个对象,如图
改正
如果需要返回一个可变对象的引用,我们应该首先对其进行克隆(clone),这样会创建一个当前对象的副本,而不会对当前对象造成影响,代码改正如下
class Example{ private Date birthday; ... public Date getBirthday{ return birthday.clone(); } ...}
2017.6.10更新
看过Date(java.util.Date)的源码的各位应该知道,Date里的clone方法返回的是一个Object对象,这会导致上面的 getBirthday 函数报错(类型不匹配,不能从Object类型转为Date),所以,这里需要将代码更正如下
class Example{ private Date birthday; ... public Date getBirthday{ return (Date) birthday.clone(); } ...}
经过这样的转换,也不会破坏封装性(因为传回来的是 birthday 的一个复制品)
后记
在编写Java代码的时候,一定要记得,Java中每声明一个类的实例名称,事实上只是声明了一个引用名称,当前实例创建是在调用new + 构造器后才创建的(类似于C/C++中的指针),所以在使用过程中一定要慎重慎重再慎重!
- Java中关于返回引用可变对象常见问题剖析
- Java不可编写返回引用可变对象的访问器方法
- Java中关于对象引用的分类
- 不可编写返回可变引用对象的访问器方法
- 不要编写返回引用可变对象的访问器
- 不要编写返回引用可变对象的访问器方法
- 不能编写返回引用可变对象的访问器方法
- 不要编写返回引用可变对象的访问器方法
- 关于JAVA中引用及返回值的问题
- 关于函数返回引用和const对象
- String中返回对象和返回对象引用的对比
- Python中引用可变对象的变量进行操作
- java中要注意对象作为参数引用返回时,对象本身是否变化了
- Java关于对象引用问题
- Java初学者常见问题_字符串序列化_可变不可变_传递(值,引用)
- 4.3 不要编写返回引用可变对象的访问器方法
- 关于Java对象与对象引用
- Java常见问题之引用相等性和对象相等性
- Kotlin学习篇(1)
- Android_布局
- PHP培训多少钱
- SpringMVC处理请求流程
- Python高级编程-深拷贝与浅拷贝
- Java中关于返回引用可变对象常见问题剖析
- 遇见JSP
- ACM:L: 素数槽
- JAVA SE
- 安卓布局
- 知乎爬虫---总结我的Java课程设计
- 欢迎使用markdown
- [Java]String、StringBuilder和StringBuffer
- Java基础应用之基本语法(输出错误信息和调试信息)