Java 为什么可以修改最终对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2435163/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why can final object be modified?
提问by Matt McCormick
I came across the following code in a code base I am working on:
我在我正在处理的代码库中遇到了以下代码:
public final class ConfigurationService {
private static final ConfigurationService INSTANCE = new ConfigurationService();
private List providers;
private ConfigurationService() {
providers = new ArrayList();
}
public static void addProvider(ConfigurationProvider provider) {
INSTANCE.providers.add(provider);
}
...
INSTANCE
is declared as final
. Why can objects be added to INSTANCE
? Shouldn't that invalidate the use of final. (It doesn't).
INSTANCE
被声明为final
. 为什么可以添加对象INSTANCE
?这不应该使 final 的使用无效。(它没有)。
I'm assuming the answer has to do something with pointers and memory but would like to know for sure.
我假设答案必须与指针和内存有关,但想确定。
采纳答案by Sean Owen
final
simply makes the object referenceunchangeable. The object it points to is not immutable by doing this. INSTANCE
can never refer to another object, but the object it refers to may change state.
final
只是使对象引用不可更改。通过这样做,它指向的对象不是一成不变的。INSTANCE
永远不能引用另一个对象,但它引用的对象可能会改变状态。
回答by Chris Dail
Final and immutable are not the same thing. Final means the reference cannot be reassigned so you can't say
Final 和 immutable 不是一回事。Final 意味着不能重新分配引用,所以你不能说
INSTANCE = ...
Immutable means that the object itself cannot be modified. An example of this is the java.lang.String
class. You cannot modify the value of a string.
不可变意味着对象本身不能被修改。这方面的一个例子是java.lang.String
类。您不能修改字符串的值。
回答by Jon Skeet
The key to the misunderstanding is in your question's title. It's not the objectwhich is final, it's the variable. The variable's value can't change, but the data within it can.
误解的关键在于您的问题标题。最终的不是对象,而是变量。变量的值不能改变,但其中的数据可以。
Always remember that when you declare a reference type variable, the value of that variable is a reference, not an object.
永远记住,当你声明一个引用类型变量时,该变量的值是一个引用,而不是一个对象。
回答by Theo
finaljust means the reference can't be changed. You can't reassign INSTANCE to another reference if it's declared as final. The internal state of the object is still mutable.
final只是意味着无法更改引用。如果声明为 final,则不能将 INSTANCE 重新分配给另一个引用。对象的内部状态仍然是可变的。
final ConfigurationService INSTANCE = new ConfigurationService();
ConfigurationService anotherInstance = new ConfigurationService();
INSTANCE = anotherInstance;
would throw a compilation error
会抛出编译错误
回答by defectivehalt
Once a
final
variable has been assigned, it always contains the same value. If afinal
variable holds a reference to an object, then the state of the object may be changed by operations on the object, but the variable will always refer to the same object. This applies also to arrays, because arrays are objects; if afinal
variable holds a reference to an array, then the components of the array may be changed by operations on the array, but the variable will always refer to the same array.
一旦
final
变量被赋值,它总是包含相同的值。如果final
变量持有对对象的引用,则对象的状态可能会因对对象的操作而改变,但变量将始终引用同一个对象。这也适用于数组,因为数组是对象;如果final
变量持有对数组的引用,则数组的组成部分可能会因对数组的操作而改变,但变量将始终引用同一个数组。
Here's a guide on making an object immutable.
这是使对象不可变的指南。
回答by OscarRyz
Being final is not the same as being immutable.
最终与不可变不一样。
final != immutable
final != immutable
The final
keyword is used to make sure the reference is not changed ( that is, the reference it has can't be substituted with a new one )
所述final
关键字被用于确保基准不会改变(即,它已经不能用新的被取代的参考)
But, if the attribute is self is modifiable it is ok to do what you have just described.
但是,如果属性 self 是可修改的,则可以执行您刚刚描述的操作。
For instance
例如
class SomeHighLevelClass {
public final MutableObject someFinalObject = new MutableObject();
}
If we instantiate this class, we won't be able to assign other value to the the attribute someFinalObject
because it is final.
如果我们实例化这个类,我们将无法为该属性分配其他值,someFinalObject
因为它是final。
So this is not possible:
所以这是不可能的:
....
SomeHighLevelClass someObject = new SomeHighLevelClass();
MutableObject impostor = new MutableObject();
someObject.someFinal = impostor; // not allowed because someFinal is .. well final
But if the object it self is mutable like this:
但是如果它自身的对象是这样可变的:
class MutableObject {
private int n = 0;
public void incrementNumber() {
n++;
}
public String toString(){
return ""+n;
}
}
Then, the value contained by that mutable object may be changed.
然后,该可变对象包含的值可能会更改。
SomeHighLevelClass someObject = new SomeHighLevelClass();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
System.out.println( someObject.someFinal ); // prints 3
This has the same effect that your post:
这与您的帖子具有相同的效果:
public static void addProvider(ConfigurationProvider provider) {
INSTANCE.providers.add(provider);
}
Here you are not changing the value of INSTANCE, your are modifying its internal state ( via, providers.add method )
在这里,您不是在更改 INSTANCE 的值,而是在修改其内部状态(通过 providers.add 方法)
if you want to prevent that the class definition should be changed like this:
如果你想防止类定义应该像这样改变:
public final class ConfigurationService {
private static final ConfigurationService INSTANCE = new ConfigurationService();
private List providers;
private ConfigurationService() {
providers = new ArrayList();
}
// Avoid modifications
//public static void addProvider(ConfigurationProvider provider) {
// INSTANCE.providers.add(provider);
//}
// No mutators allowed anymore :)
....
But, it might not make much sense :)
但是,这可能没有多大意义:)
By the way, you also have to synchronize access to itbasically for the same reason.
顺便说一句,出于同样的原因,您还必须同步对它的访问。
回答by Steve Kuo
Java doesn't have the concept of immutability built into the language. There is no way to mark methods as a mutator. Therefore the language has no way to enforce object immutability.
Java 没有内置于语言中的不变性概念。没有办法将方法标记为mutator。因此,该语言无法强制执行对象不变性。