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

Java 一旦调用构造函数,我可以使对象不可变吗?,java,immutability,Java,Immutability,类X的对象在类Other的构造函数中初始化 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 getx1

类X的对象在类Other的构造函数中初始化

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; }
}
我想以某种方式摆脱
classx
中的许多
getter
方法。我可以简单地删除它们并使
X
的所有数据成员位于
default
范围内(
X
仅在包中使用)

调用构造函数
Other
后,有没有办法使
xobj
的成员不可变?这里的想法是,当使用
get()
方法时,不能修改
X
中的变量

class Other
{
  private X obj;
  // Other members
  public Other ()
  {
    obj = new X(this);
    //...
  }
  //...
}
现在,如果我只使用
obj.x1
,那么它可能会被覆盖(或者至少在代码审查中,它会被反对)


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

getter方法不会使实例可变。这将是setter方法。您的
X
(如定义)已经是不可变的-任何东西都不能更改实例的
X
值,它们只能通过getter检索


如果您问的是如何摆脱getter方法并允许直接访问成员变量:任何体面的JVM都会通过其JIT编译器内联这些getter函数,使它们成为直接的成员检索。因此,如果您保留了getter,那么您就可以保持更改的灵活性,几乎不需要任何成本。

getter方法不会使实例可变。这将是setter方法。您的
X
(如定义)已经是不可变的-任何东西都不能更改实例的
X
值,它们只能通过getter检索


如果您问的是如何摆脱getter方法并允许直接访问成员变量:任何体面的JVM都会通过其JIT编译器内联这些getter函数,使它们成为直接的成员检索。因此,如果您保留了getter,那么您就可以保持更改的灵活性,几乎不需要任何成本。

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

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

下面是如何使类不可变的:

obj.getx1();
然而,去掉这些getter通常是个坏主意。例如:

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

  • 可以在子类中重写getter,但裸属性不能

  • getter允许将对象用作“javabean”


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

下面是如何使类不可变的:

obj.getx1();
然而,去掉这些getter通常是个坏主意。例如:

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

  • 可以在子类中重写getter,但裸属性不能

  • getter允许将对象用作“javabean”


而getter的存在或不存在并不能使类不可变。

使类不可变(而不是不可变)的最佳方法是将所有字段标记为
final
(可见性是无关的,可以是
public
)。字段必须使用初始值设定项进行初始化:

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; }
}
或在每个构造函数中:

class A { final int x = 10; }

使类不可变(而不是不可变)的最佳方法是将所有字段标记为
final
(可见性是不相关的,可以是
public
)。字段必须使用初始值设定项进行初始化:

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; }
}
或在每个构造函数中:

class A { final int x = 10; }

甚至最好将字符串实例声明为final,因为它们永远不会更改。如果对象实例在不同线程之间来回抛出,这是一个特别好的主意。实际上,我想去掉
getter
,同时避免在使用as
obj.x1时覆盖
x1,x2
,甚至最好将字符串实例声明为final,因为它们永远不会更改。如果对象实例在不同线程之间来回抛出,这是一个特别好的主意。实际上,我想去掉
getter
,还想避免在使用as
obj.x1时覆盖
x1,x2