如何在Java中强制实现自定义类实例不变量

时间:2013-06-14 08:38:20

标签: java design-by-contract invariants

Java中强制执行类实例不变量的最佳方法是什么(即在调用任何公共方法之前和之后确保某些语句为真)?

我将在下面举一个例子(让我对这个问题感到疑惑的一个例子),但事实上我对强加类实例不变量的一般解决方案更感兴趣。

假设我有以下课程:

public class Constraint
{
  private int cardinality;

  // constructor and getter/setter omitted
}

public class Edge
{
  private int minCardinality = 1;
  private int maxCardinality = Integer.MAX_VALUE;
  private Constraint constraint = null;

  // constructors, getters/setters and other methods omitted
}

并且我想在Edge类上强制执行以下语句:

  • 0< = minCardinality< = maxCardinality
  • if(constraint!= null)then(minCardinality< = constraint.getCardinality()< = maxCardinality)

此处,Edge实例由具有(强制)属性minCardinality和maxCardinality集的解析器创建。 (可选)约束属性保留为空。然后将实例移交给另一个模块(测试帧生成器),该模块可能会或可能不会通过setter方法设置约束。

1 个答案:

答案 0 :(得分:4)

使用建筑商并将支票放入其中;这样你的Edge课就不在乎了:

@Immutable // See JSR 305
public final class Edge
{
    private final int minCardinality;
    // ...

    public static Builder newBuilder() { return new Builder(); }

    // Edge has no public constructor anymore, only this one:
    private Edge(final Builder builder)
    {
        minCardinality = builder.minCardinality;
        // etc
    }

    @NotThreadSafe // See JSR 305
    public static final class Builder
    {
        private int minCardinality;
        // ...

        private Builder() {}

        public Builder withMinCardinality(final int minCardinality)
        {
            this.minCardinality = minCardinality;
            return this;
        }
        // etc

        public Edge build()
        {
            // checks here
            return new Edge(this);
        }
    }
}

用法:

final Edge edge = Edge.newBuilder().withMinCardinality(xxx).etc().etc().build();