我正在学习不可变的对象。我正在尝试这段代码
public final class ImmutableObject {
private final String name;
private final NormalObject obj = new NormalObject();
public String getName() {
return name;
}
public ImmutableObject(String name) {
this.name = name;
obj.setName(name);
}
public NormalObject getObj() {
NormalObject tempObj = obj;
return tempObj;
}
}
public class NormalObject {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
我想限制调用类更改NormalObject的名称变量的值
但是以下代码更改了值
ImmutableObject obj = new ImmutableObject("Siddle");
System.out.println(obj.getObj().getName()); //prints Siddle
obj.getObj().setName("Kelly");
System.out.println(obj.getObj().getName()); //prints Kelly
如何限制它?
答案 0 :(得分:5)
对于不可变的对象,其所有属性必须是不可变的。它的状态一定不能改变。
要做到这一点,你必须在NormalObject
上放置一个不可变的外观,你不能直接返回NormalObject
。返回它的方法也需要一个不同的返回类型,你不能返回NormalObject
但实际上返回的行为不像NormalObject
。
E.g:
public final class ImmutableObject {
private final String name;
private final NormalObject obj = new NormalObject();
private final ImmutableNormalObject objFacade = new ImmutableNormalObject(obj);
public String getName() {
return name;
}
public ImmutableObject(String name) {
this.name = name;
obj.setName(name);
}
public ImmutableNormalObject getObj() {
return objFacade;
}
}
public class NormalObject {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class ImmutableNormalObject {
private NormalObject obj;
public ImmutableNormalObject(Normalobject o) {
this.obj = o;
}
public String getName() {
return obj.getName();
}
}
或者,如果复制对象并且它有一个复制构造函数(或者你可以添加一个)是可以接受的,那么你可以这样做,但复制和返回是很昂贵的。
答案 1 :(得分:0)
您可以通过在getter中返回normalObject
的副本来执行此操作:
public NormalObject getObj() {
return new NormalObject(obj.getName());
// or you can make a copy constructor:
// return new NormalObject(obj);
}
或者你可以为NormalObject
制作一个忽略名字设定器的包装器,但它会制动逻辑。
答案 2 :(得分:0)
请将您的NormalObject代码更改为
public final class ImmutableObject {
private final String name;
// initialise it to null
private final NormalObject obj = null;
public String getName() {
return name;
}
public ImmutableObject(String name) {
this.name = name;
// use the Constructor for setting name only once during initialization of ImmutableObject via its constructor
obj = new NormalObject(name);
//obj.setName(name);
}
public NormalObject getObj() {
NormalObject tempObj = obj;
return tempObj;
}
}
NormalObject Class
public class NormalObject {
private String name;
public NormalObject(name){
this.name = name;
}
public String getName() {
return name;
}
//Remove any setter on NormalObject
/*public void setName(String name) {
this.name = name;
}*/
}
答案 3 :(得分:0)
在不可变对象中,如果用户尝试更改对象的状态。您将不允许或返回Immutable类的新实例。
因此,由于Date是一个可变的类。 您可以在日期周围创建一个不可变包装器,并且只能公开那些在不可变日期视图中使用的方法,但是您将返回一个不可变类的新实例,并带有新Date的更改属性。
我认为Immutable变量不需要final,因为它已经是私有且不可变的。
示例:
public class Main{
private ImmutableDate immutableDate;
public Main() {
this.immutableDate = new ImmutableDate(new Date());
}
public Main(Date date){
this.immutableDate = new ImmutableDate(date);
}
public ImmutableDate getDate() {
return immutableDate;
}
public class ImmutableDate{
// private constructor, so this can only be instantiated within the outer class
// therefore, final keyword not required for Date, as no access given to the variable
private Date date;
private ImmutableDate(Date date) {
this.date = date;
}
// Example methods from Date, that are required for our Immutable implementation
public Main setTime(long time){
Date date1 = new Date();
date1.setTime(time);
return new Main(date1);
}
@Override
public String toString() {
return date.toString();
}
}
}