java - 单例模式

标签 java singleton

这个问题和我之前的问题一样,引用了 Effective Java。这次我有很多子问题。

  1. 特权客户端可以借助 AccessibleObject.setAccessible() 方法以反射方式调用私有(private)构造函数。如果您需要对此进行防御,请修改构造函数。
    究竟如何调用私有(private)构造函数?什么是 AccessibleObject.setAccessible()

  2. 你们专家对单例采用什么方法?

    // 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; }
        .
        .
        .
    }
    

    如果我们每次都必须检查新实例或每次都检查同一个实例,第二种方法不是更灵活吗?

  3. 如果我尝试克隆类/对象会怎样?

  4. 单元素枚举类型是实现单例的最佳方式。
    为什么?如何?

最佳答案

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/

相关文章:

qt - Qt 的 GUI 编程中的单例是邪恶的吗?

c# - 我的 HttpClient 单例实现是否合适?

Java EE 的 CDI 没有按预期工作

java - NetBeans Gradle项目

java - 将音频文件切成几段(java)

java - 如何在Java中对类及其子类使用泛型?

java - 无法更改 JTextField 文本

multithreading - 初始化没有魔法静态的空多态单例类型

c++ - 为什么要避免在 C++ 中使用单例

java - JSONObject 使用单例