[英]Is it possible to do a final class immutable in Java?
Recently on the interview I had an interesting question. 最近在采访中,我有一个有趣的问题。 We have mutable class:
我们有可变的类:
final class Example {
private int i;
private String s;
private Object o;
// get, set
}
And instance of this class Example e = new Example();
此类的
Example e = new Example();
Can we somehow make this instance immutable? 我们可以以某种方式使该实例不可变吗? Without changing original class.
无需更改原始类。
My thoughts: 我的想法:
If you are unable to make modifications to the Example
class and you cannot subclass it (in your snippet, it is marked as final
) the closest solution I can think of is to create a wrapper class, which is immutable. 如果您无法进行修改的
Example
类,你不能继承它(在你的代码片段,它被标记为final
)我能想到的最接近的解决方案是创建一个包装类,这是不可改变的。 This is not a perfect solution, and has it's drawbacks. 这不是一个完美的解决方案,它有缺点。
First, how to do it: 首先,如何做:
final class ImmutableExample {
// Redeclare every field as in the Example class
// but make sure they can't be reassigned
// (in this case I'll declare them as final)
private final int i;
private final String s;
private final Object o;
ImmutableExample(Example mutableExample) {
// copy fields from original
this.i = mutableExample.getI();
this.s = mutableExample.getS();
this.o = mutableExample.getO();
}
// add getters but definitely no setters
}
Then everywhere you have code like this: 然后到处都有这样的代码:
Example e = new Example();
e.setI(42); // etc
Change to: 改成:
Example e = new Example();
e.setI(42); // etc
ImmutableExample immutableE = new ImmutableExample(e);
And pass around references to immutableE
, and make sure that the e
reference does not escape. 并传递对
immutableE
引用,并确保e
引用不会转义。
Now, for the drawbacks: 现在,对于缺点:
ImmutableExample
is not an instance of Example
, so you cannot pass the immutable type to a method which expects the mutable type, and operations like if (immutableE instanceof Example)
or (Example)immutableE
will not work as before ImmutableExample
不是Example
,因此您不能将不可变类型传递给需要可变类型的方法,并且if (immutableE instanceof Example)
或(Example)immutableE
将无法像以前那样工作
You have to be very careful that every field of Example
is also immutable, or ImmutableExample
will also be mutable. 您必须非常小心,
Example
每个字段也是不可变的,否则ImmutableExample
也是可变的。 Consider, for example, that the field of type Object
could be something mutable, like a HashMap
or a Date
. 例如,考虑类型为
Object
的字段可以是可变的,例如HashMap
或Date
。
When the Example
class changes, you have to repeat the change in ImmutableExample
. 当
Example
类更改时,必须在ImmutableExample
重复更改。
If it was possible to subclass Example
, or if it was an interface, this approach might be more useful, but I can't see any other way when Example
cannot be subclassed. 如果可以将
Example
子类化,或者如果它是一个接口,则此方法可能更有用,但是在不能对Example
子类化时,我看不到任何其他方式。
If each of those fields have getters/setters, then to make it immutable, you will have to 如果每个字段都有getter / setter,那么要使其不可变,您将必须
private
and final
private
和final
Immutability is a property of a class not an instance. 不变性是类的属性,而不是实例。 So besides bytecode twiddling or other means to change the class;
因此,除了字节码纠缠或其他更改类的方法外; not possible.
不可能。
With a none final class i would create an immutable decorator. 如果没有最终类,我将创建一个不变的装饰器。 That would not make the instance immutable, but provide an immutable wrapper to that instance.
这不会使实例不可变,但会为该实例提供不可变的包装。
You could not assign the instance to any variable/field, making it impossible to change it ;) 您无法将实例分配给任何变量/字段,因此无法更改它;)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.