Java 一旦调用构造函数,我可以使对象不可变吗?
类X的对象在类Other的构造函数中初始化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
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
,同时避免在使用asobj.x1时覆盖x1,x2
,甚至最好将字符串实例声明为final,因为它们永远不会更改。如果对象实例在不同线程之间来回抛出,这是一个特别好的主意。实际上,我想去掉getter
,还想避免在使用asobj.x1时覆盖x1,x2