2

我有一个对象:

Object obj = create();

...我需要设置这个对象的一些属性:

obj.setParam("7696969", 0x506);

在此过程之后,我需要确保obj无法修改。

有没有办法设置objfinal不创建另一个final Object副本obj

4

5 回答 5

11

考虑为新创建的对象使用Builder设计模式。

FooBuilder builder = new FooBuilder();
builder.setParam(...);
builder.setBar(...);

final Foo myFoo = builder.build();

请注意,即使myFoo是最终的,它的成员字段也可能不是。你也不应该忘记声明那些最终的。

于 2013-08-22T20:40:07.593 回答
3

final 关键字不会阻止对象的内部变量被修改。final 关键字所做的就是防止变量被重新分配。

防止内部被修改需要对象本身的特定设计。

不能重新分配内部变量的对象称为不可变对象。您可以使用私有访问修饰符创建不可变对象,并且不创建set函数。还要确保将所有内部变量声明为final.

Amir 对 Builder 设计的参考是一个很好的建议。具有构建器模式的不可变对象将非常适合您。

于 2013-08-22T20:41:34.707 回答
0

你想要一个不可变的类。这是一个例子。

class Foo
{
    private string s;
    private int i;

    public Foo(string s, int i)
    {
        this.s = s;
        this.i = i;
    }

    public string getS() { return s; }
    public int getI() { return i; }
}

Builder 设计模式通常是矫枉过正的。

于 2013-08-22T20:54:04.293 回答
0

如果不使用 Builder 模式,您可以做的是

    public class MyImmutableClass {
         final private String foo;
         final private String bar;
         public MyImmutableClass(String f, String b) {
              this.foo = f;
              this.bar = b;
         }

         // only getters
    }

它的工作方式是

  1. 使所有字段最终
  2. 不提供二传手
  3. 确保子类不能覆盖任何方法(使类最终)

如果构造函数中的参数数量增加,构建器模式会派上用场。您只是使用构建器使您的代码更易于维护和可读,但策略几乎相同,即它还允许仅通过内部静态类进行对象操作并在主/外部类中公开只读(getter)方法

使用 builder 的另一个原因可能是您的对象具有一些强制性和可选参数。

    public class Item {
       // private fields & getters

         public static class Builder {
              // same private fields
              public Builder(String f, String b) {
                 // set values
              }
              ...
              ...
         }
     }

在这里,您可以使用内部public Builder(String f, String b)构造函数来获取两个强制参数,将其余参数保持为可选

如果参数数量较少,我认为第一种策略比实现构建器效果更好,因为它具有代码重复的缺点(构建器需要从外部类复制所有字段)

于 2013-08-23T20:01:11.330 回答
0

如果你真的需要通过setter单独设置参数,那么你将不得不做一些简单的算法。例如,当对象必须变为不可变时,您可以提供一个布尔标记,在初始化过程之后将该布尔值设置为 true,所有设置器将在决定是否可以使用新值重置当前值之前检查该布尔值。

当您没有本机机制为您完成繁重的工作时,您必须想出一个可以完成这项工作的算法:)

于 2013-08-22T20:46:54.920 回答