一旦调用构造函数,我可以使对象不可变吗?

时间:2011-06-23 09:15:26

标签: java immutability

class X
{
  String x1;
  String x2;
  //...
  String x15;

  public X (Other o)
  {
    // initialize x1,x2,...,x15
  }

  String getx1 () { return x1; }  // lot of getters
  String getx2 () { return x2; }
  //...
  String getx15 () { return x15; }
}

class X的对象在class Other;

的构造函数中初始化
class Other
{
  private X obj;
  // Other members
  public Other ()
  {
    obj = new X(this);
    //...
  }
  //...
}

我想以某种方式摆脱getter中的许多class X方法。我可以简单地删除这些内容,并使X范围内的default的所有数据成员(X仅在包中使用)。

在调用构造函数X obj之后,有什么方法可以使Other的成员不可变?这里的想法是,当使用get()方法时,X中的变量无法修改。

obj.getx1();

现在,如果我只使用obj.x1,那么它可能会被覆盖(或者至少在代码审查中会被反对)。

[注意:obj必须仅在Other()构造函数中初始化。

4 个答案:

答案 0 :(得分:2)

如果您将成员变量声明为final,那么它们在构造函数之后是不可变的。

答案 1 :(得分:2)

以下是如何使类不可变:

class X {
  private final String x1;
  private final String x2;

  public X (Other o)
  {
    x1 = o.getX1();
    x2 = o.getX2();
  }

  String getX1 () { return x1; } 
  String getX2 () { return x2; }
}

然而,摆脱吸气剂通常是一个坏主意。例如:

  • Getters减少了耦合,并允许在不破坏客户端代码的情况下更改xn字段的实际实现类型。

  • 可以在子类中覆盖getter,但不能覆盖裸属性。

  • Getters允许将该对象用作“Java bean”。

getter的存在与否并不会使该类不可变。

答案 2 :(得分:1)

getter方法不会使实例变为可变。那将是 setter 方法。您定义的X已经是不可变的 - 没有任何内容可以更改实例的x值,它们只能通过getter 检索

如果您正在询问如何摆脱getter方法并允许直接访问成员变量:任何体面的JVM都会通过其JIT编译器内联这些getter函数,从而使它们成为直接成员检索。因此,如果您保留吸气剂,您可以保持灵活的线下变化,几乎不需要任何费用。

答案 3 :(得分:1)

使类不可变(不是不可变)的最佳方法是将所有字段标记为final(可见性无关紧要,可以是public)。必须使用初始化程序初始化字段:

class A { final int x = 10; }

或在每个构造函数中:

class A { 
   final int x, y, z;
   A(int x, int y, int z) { this.x = x;, this.y = y; this.z = z; }
   A() { this (0, 0, 0); }
}