我在我正在处理的代码库中遇到以下代码:
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);
}
...
Run Code Online (Sandbox Code Playgroud)
INSTANCE被宣布为final.为什么可以添加对象INSTANCE?不应该使final的使用无效.(它没有).
我假设答案必须用指针和内存做一些事情,但我想肯定知道.
Osc*_*Ryz 33
最终与不可变是不一样的.
final != immutable
所述final关键字被用于确保基准不会改变(即,它已经不能用新的被取代的参考)
但是,如果属性是self是可修改的,那么你可以按照你刚才描述的那样做.
例如
class SomeHighLevelClass {
public final MutableObject someFinalObject = new MutableObject();
}
Run Code Online (Sandbox Code Playgroud)
如果我们实例化这个类,我们将无法为该属性分配其他值,someFinalObject因为它是最终的.
所以这是不可能的:
....
SomeHighLevelClass someObject = new SomeHighLevelClass();
MutableObject impostor = new MutableObject();
someObject.someFinal = impostor; // not allowed because someFinal is .. well final
Run Code Online (Sandbox Code Playgroud)
但如果它自己的对象是可变的,就像这样:
class MutableObject {
private int n = 0;
public void incrementNumber() {
n++;
}
public String toString(){
return ""+n;
}
}
Run Code Online (Sandbox Code Playgroud)
然后,可以改变该可变对象包含的值.
SomeHighLevelClass someObject = new SomeHighLevelClass();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
System.out.println( someObject.someFinal ); // prints 3
Run Code Online (Sandbox Code Playgroud)
这与你的帖子有同样的效果:
public static void addProvider(ConfigurationProvider provider) {
INSTANCE.providers.add(provider);
}
Run Code Online (Sandbox Code Playgroud)
这里你没有改变INSTANCE的值,你正在修改它的内部状态(via,providers.add方法)
如果你想防止类定义应该像这样改变:
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 :)
....
Run Code Online (Sandbox Code Playgroud)
但是,它可能没有多大意义:)
顺便说一句,您还必须基本上以同样的原因同步对它的访问.
小智 11
final只是意味着引用无法更改.如果将INSTANCE声明为final,则无法将其重新分配给另一个引用.对象的内部状态仍然是可变的.
final ConfigurationService INSTANCE = new ConfigurationService();
ConfigurationService anotherInstance = new ConfigurationService();
INSTANCE = anotherInstance;
Run Code Online (Sandbox Code Playgroud)
会抛出编译错误
最终和不可变不是一回事。Final 意味着引用不能被重新分配,所以你不能说
INSTANCE = ...
Run Code Online (Sandbox Code Playgroud)
不可变意味着对象本身不能被修改。类就是一个例子java.lang.String。您无法修改字符串的值。
| 归档时间: |
|
| 查看次数: |
54527 次 |
| 最近记录: |