有没有办法确保在编译时设置不可变对象中的某些字段,同时保持参数的作用清晰?

时间:2011-04-05 19:15:25

标签: java immutability

我正在尝试创建不可变对象的方法。以下构建器对象 非常有吸引力,因为他们保持了论点的作用。不过我想 使用编译器验证是否设置了某些字段,就像使用Immutable()构造函数调用一样。 StrictImmutableBuilder提供这些检查,但相当嘈杂。有没有办法获得相同的检查,但形式为LaxImmutableBuilder?也许使用注释?

public class Immutable {

    public static void main(String[] args) {

        new Immutable("13272873C", 23, false);
        // nice but what where those arguments?

        new LaxImmutableBuilder() {{
            refCode("13272873C");
            age(23);
            subscribed(false);
        }}.build();
        // now I know what each value represents
        // but what if I forgot to set one?

        new StrictImmutableBuilder() {
            public String refCode() { return "13272873C"; }

            public int age() { return 23; }

            public boolean subscribed() { return false; }
        }.build();
        // now I'm forced to set each field, but now 
        // we have the extra noise of "return"
        // and also "public" if we want to use
        // this outside the current package

        // is there another way? maybe using annotations?
    }

    private final String refCode;
    private final int age;
    private final boolean subscribed;

    public String getRefCode() {
        return refCode;
    }

    public int getAge() {
        return age;
    }

    public boolean isSubscribed() {
        return subscribed;
    }

    public Immutable(String a, int b, boolean c) {
        this.refCode = a;
        this.age = b;
        this.subscribed = c;
    }

}

abstract class StrictImmutableBuilder {
    public abstract String refCode();

    public abstract int age();

    public abstract boolean subscribed();

    public Immutable build() {
        return new Immutable(refCode(), age(), subscribed());
    }
}

abstract class LaxImmutableBuilder {

    private String refCode;
    private int age;
    private boolean subscribed;

    protected void refCode(String refCode) {
        this.refCode = refCode;
    }

    protected void age(int age) {
        this.age = age;
    }

    protected void subscribed(boolean subscribed) {
        this.subscribed = subscribed;
    }

    public Immutable build() {
        return new Immutable(refCode, age, subscribed);
    }

}

2 个答案:

答案 0 :(得分:2)

这是我使用的模式:

class YourClass {
  // these are final
  private final int x;
  private final int y;

  private int a;
  private int b;

  // finals are passed into the constructor
  private YourClass(int x, int y) {
    this.x = x;
    this.y = y;
  }

  public static class Builder {
    // int x, int y, int a, int b
    // whatever's final is passed into constructor
    public Builder(int x, int y) {
      this.x = x;
      this.y = y;
    }
    // a and b are optional, so have with() methods for these
    public Builder withA(int a) {
      this.a = a;
      return this;
    }
    public Builder withB(int b) {
      this.b = b;
      return this;
    }
    public YourClass build() {
      YourClass c = new YourClass (x, y);
      c.a = a;
      c.b = b;
      return c;
    }
  }
}

答案 1 :(得分:0)

有这个技巧:类型安全的构建器模式

http://michid.wordpress.com/2008/08/13/type-safe-builder-pattern-in-java/

但那太疯狂了。