How to make the return immutable in JAVA
我有一个物体,比如
1 2 3 4 5 6 7 8
| public class ABC {
private String a ;
private String b ;
private String c ;
//getters and setters
} |
此对象是从集合(如ArrayList中的方法)返回的。
我只想使返回不可变,而不更改对象中的任何内容。有人能帮我吗?
- 我喜欢@murtazazaidi的回答,但是如果你必须有自己的设置者,请返回对象的副本。
- 在爪哇,没有任何东西可以支持你想要的(让对象不变,而不改变类/写类首先是不可变的)。
- @欧文。我不能退回对象的副本吗?
- @加根肯定,但那份拷贝是可变的。除非您将所有数据复制到第二个类的一个对象中,而该对象是写为不可变的。
- @欧文。唯一的办法就是改变我的班级。正确的?我得把课堂上的课业定为期末考试。以及班级本身……但我仍然可以拥有盖特和塞特?
不要提供setter(mutators),将不可变的属性设为private,只通过构造函数提供值赋值。
您总是可以声明不可变的属性final。所以您只能给它们赋值一次,以后不能更改它们。
- 吸气剂怎么了?
- 我不想更改我的对象。方法返回arraylist。我可以让我的回报不变吗?
- 为什么不呢?
- 他不应该在属性上使用final修饰符吗?这样可以确保字段是不可变的。
- @对于一个对象,某些字段不可能保持不变,而对于同一类的其他对象,则不可能保持不变。您可以使用类似的成员创建另一个类,使其属性成为最终属性,并在其构造函数中传递来自该类对象的值。
- @ Murtaza…所以我必须改变我的班级,让这门课成为最后一门课。还有课吗?
- 您的问题是,您不希望使类不可变,而是返回其对象的图像,该图像保持不变。解决方法是做两个类似的类。但一个是不变的,另一个不是。使用不可变类的对象返回。你明白了吗?
只使用getter的接口
A是您的具体(impl)类
接口编码?
1
| public I getA(){ retrun AImpl();} |
哪里
1 2
| public interface I { public String getOne ()}
public AImple implements I {... } |
当前类中唯一的"更改"是"implements i"
JDK和ApacheCommons使用装饰器
http://grepcode.com/file/repository.jboss.org/nexus/content/repository/releases/org.jboss.embedded/thirdparty-all/beta3.sp15/org/apache/commons/collections/list/unmodifiablelist.java
另一个解决方案
克隆您的对象并返回它,这样副本就更改了,原始对象保持不变。
- 这种方法是不安全的,因为没有什么可以阻止代码调用getA(),将返回的类型强制转换为实例的实际类型,并随意操作它。
- 如果您的计算机正在运行,您可以编写另一个程序来查找对象内存并将0更改为1,这与安全无关。
如果对象的类提供了突变,则不能使其不可变。对象始终提供由其类定义的所有功能。
因此,如果您想要一个不可变的对象,那么您需要一个不可变的类。如果您不能更改相关的类,那么像@duffymo这样的包装类就可以达到这个目的。但是,请注意,这样一个类的对象不能与包装类的对象互换,并且您需要以某种方式提供应用包装器。
如果您需要与ABC类的对象完全可互换的对象,那么您必须坚持这样一个事实:ABC是可变的,因此任何与ABC可互换的对象都是可变的,至少在ABC的可变方面是可变的。然后,归根结底就是为什么你想要不变。如果重点是避免改变List引用的对象,那么复制这些对象(到适当的深度)是一种替代方法。
作为第三种选择,如果目标类没有非私有字段,那么您可以创建一个子类,重写setter使其无效,或者抛出一些未经检查的异常。在这种情况下,请注意
这样的子类形式不好,它的实例与ABC类的实例不能真正互换。
如果类abc具有可变类型的可访问属性(例如可变容器),那么您可能还需要做一些事情来防止这些对象发生变化。递归地。
是的,这真是一团糟。
- 如果你使用接口,你(几乎)可以
- @约翰。谢谢。。我有一个方法返回abc的arraylist。我想让这个结果不变。我现在明白了。除非类是不可变的,否则我不能使它不可变。
- Oracle、Oracle、COM/JavaSe/ 7 /DOCS/API/Java/UTL/HelLIP;将确保列表本身不可修改,不返回数组列表。
- @ Kaplesh。这行吗……collections.unmodifiablecollection(results);如果结果是ABC的集合
- @Kaplesh是的,如果声明的List的元素类型是不提供setter的接口类型,那么List的使用者在不知道实际的元素类和强制转换的情况下无法修改元素。这是一个很好的方法,但它不能使元素真正不变。另外,改变List的类型参数可能是不可行的。
- @kalpesh collections.unmodifiablelist()将提供一个List包装器,通过它元素既不能添加到基础List中,也不能从基础List中删除。这决不会使元素本身不可变,而且它甚至不会阻止直接修改原始列表。
- 使用接口而不是类(只有getter)放入列表?