这个问题和我之前的问题一样,引用了 Effective Java。这次我有很多子问题。
特权客户端可以借助
AccessibleObject.setAccessible()
方法以反射方式调用私有(private)构造函数。如果您需要对此进行防御,请修改构造函数。
究竟如何调用私有(private)构造函数?什么是AccessibleObject.setAccessible()
?你们专家对单例采用什么方法?
// Approach A public class Test{ public static final Test TestInstance = new Test(); private Test(){ ... } . . . } // Approach B public class Test{ private static final Test TestInstance = new Test(); private Test(){ ... } public static Test getInstance() { return TestInstance; } . . . }
如果我们每次都必须检查新实例或每次都检查同一个实例,第二种方法不是更灵活吗?
如果我尝试克隆类/对象会怎样?
单元素枚举类型是实现单例的最佳方式。
为什么?如何?
最佳答案
A priviledged cleint can invoke the private constructor reflectively with the aid of the AccessibleObject.setAccessible method, If you need to defend this, modify the constructor. My question is: How exactly can a private constructor is invoked? and what is AccessibleObject.setAccessible??
显然,类本身可以调用私有(private)构造函数(例如,从静态工厂方法)。反射(reflection)一下,Bloch 所说的是这样的:
import java.lang.reflect.Constructor;
public class PrivateInvoker {
public static void main(String[] args) throws Exception{
//compile error
// Private p = new Private();
//works fine
Constructor<?> con = Private.class.getDeclaredConstructors()[0];
con.setAccessible(true);
Private p = (Private) con.newInstance();
}
}
class Private {
private Private() {
System.out.println("Hello!");
}
}
2.What approach do you experts follow with singletons:
...
通常,第一个受到青睐。第二个(假设您要在返回新实例之前测试 TestInstance
是否为 null)以需要同步或线程不安全为代价获得延迟加载。
当您的第二个示例在声明时未将实例分配给 TestInstance
时,我写了上面的内容。如现在所述,上述考虑无关紧要。
Isn't the second approach more flexible in case we have to make a check for new instance every time or same instance every time?
这与灵 active 无关,而是关于何时产生创建一个(且唯一)实例的成本。如果您选择 a),它会在类加载时发生。这通常很好,因为该类只会在需要时加载。
当您的第二个示例在声明时未将实例分配给 TestInstance
时,我写了上面的内容。如现在所述,在这两种情况下,单例都将在类加载时创建。
What if I try to clone the class/object?
出于显而易见的原因,单例不应允许克隆。应该抛出 CloneNotSupportedException,除非您出于某种原因实现 Cloneable
,否则它将自动抛出。
a single-element enum type is the best way to implement a singleton. Why? and How?
这方面的例子和理由都在书中。哪一部分没看懂?
关于java - 单例模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4081227/