Java:Is setter应该使用“Clone”或it';什么是呼叫方传递的“新”副本?

Java:Is setter应该使用“Clone”或it';什么是呼叫方传递的“新”副本?,java,coding-style,clone,getter-setter,cloneable,Java,Coding Style,Clone,Getter Setter,Cloneable,如果我想确保在调用setter之后不能从外部修改对象,那么什么是最佳和常见的做法?在代码中有一个详细的简单自我解释示例,有两个选项 //caller scope CustomObject original = new CustomObject(params...); //original state 1 MyClass mMyClass = new MyClass(original); original.modifyMe(params...); //original state 2 mMyC

如果我想确保在调用setter之后不能从外部修改对象,那么什么是最佳和常见的做法?在代码中有一个详细的简单自我解释示例,有两个选项

//caller scope
CustomObject original = new CustomObject(params...);  //original state 1
MyClass mMyClass = new MyClass(original);
original.modifyMe(params...);  //original state 2
mMyClass.setCustomObject(original);
original.modifyMe(params...); //original state 3


/*!!!REQUIREMENT: mMyClass.CustomObject should be in state 2!!!*/


class MyClass {

    private CustomObject mObject;

    public MyClass() {
        this.mObject = new CustomObject();
    }

    public MyClass(CustomObject obj) {
        this.mObject = obj.Clone();
    }

    //mObject is private, modified only through setter
    public getCustomObject() {
        return this.mObject;
    }

    public setCustomObject(CustomObject obj) {
        //Option 1 in the caller  
        //mMyClass.setCustomObject(new CustomObject(params...));
        this.mObject = obj;

        //Option 2 in the caller
        //mMyClass.setCustomObject(callerCustomObject);
        this.mObject = obj.Clone();
    }

}

我不会在这里使用克隆。与其制作低效的防御副本,不如尝试使CustomObject不可变。您可以通过添加withXXX方法(大致相当于setXXXX)来修改状态,但它们会创建宿主对象的新实例(而不是传入的对象)。附带了一些方便的预处理器注释,用于创建带有Withers的不可变对象。另请参见Immutables 2.0项目

@AllArgsConstructor
class CustomObject {

   @Wither @Getter
   private final int state;

}

CustomObject one = new CustomObject(1);
CustomObject two = one.withState(2);

assertThat(one.getState(),equalTo(1));
assertThat(two.getState(),equalTo(2));

通过使用真正的不可变对象,您将比使用防御副本产生更少的内存(&GC)和CPU开销,以及更简单的代码。

如果您想确保对象不能在类外修改,您必须在类内和类外创建副本。但是不要使用
clone
-对象应该有一个复制构造函数。@realponsibilist 1。为什么在get中使用复制?我不知道,也许从外面看,他们只是想使用而不是修改对象,我认为最好是在方向上进行检查。2.在java中,复制构造函数是什么意思?这不是我们需要Clone()的原因?如果
获取对象,则可以更改它,它将更改类内的对象。所以一定要同时抄写
clone()
是。@Real怀疑论者我实现Clonebale接口并用复制构造函数样式重写克隆-这是最佳做法吗?最佳做法是不实现
Cloneable
也不重写
clone