我有這個簡單枚舉充當一個Singleton提供商爲Object
類型的對象辛格爾頓總是可以反映(反射甚至枚舉)
package package2;
public enum SingletonEnum {
INSTANCE;
private Object obj = new Object();
public Object getObject() {
return obj;
}
}
,我有這個樣品主要反映現場情況,修改通過分配新對象字段
package package2;
import java.lang.reflect.Field;
public class Sample2 {
public static void main(String[] args) {
Object obj = SingletonEnum.INSTANCE.getObject();
System.out.println(obj.hashCode());
try {
Class<?> clazz = Class.forName("package2.SingletonEnum");
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.getType().equals(Object.class)) {
field.setAccessible(true);
field.set(SingletonEnum.INSTANCE, new Object());
}
}
}
catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(SingletonEnum.INSTANCE.getObject().hashCode());
}
}
輸出是
1554514352
2112239710
顯示兩個不同的哈希碼,我假設有兩個引用。這怎麼可能?我認爲枚舉Singletons是使Singleton「Singleton」不能被反射的唯一方法,所以這隻意味着只有SecurityManager
可以禁止所有的反射。所以我的問題是......「什麼」是禁止一個Singleton對象實例化的最安全的方法?
目前還不清楚你在問什麼。 'SingletonEnum.INSTANCE' *是*單身人士。這並不意味着它是不可變的。此外,當你修改單例的字段時,其他對象的實例化不會發生,當你執行'new Object()'時,它已經發生了。 – Holger