使用Class.forName()实例化单例对象?

时间:2009-07-14 20:12:12

标签: java constructor singleton default instance

我想从字符串中实例化一个类的一个实例 班级名称。 (使用Class.forName()。newInstance()。)

问题在于:我希望该实例成为单身人士.. 我可以使用单例模式来做到这一点,除了 newInstance调用类的默认构造函数, 并且使用单例,该构造函数必须是“私有的”..

有解决方案吗?我可以想到一种不那么优雅的方式 这样做(使用hashmap作为查找表..),但更喜欢 一个更好的解决方案..

谢谢,

5 个答案:

答案 0 :(得分:8)

经典单例还有一个静态getInstance()方法 - 通过反射调用而不是使用newInstance()。是的,这是更多的工作,但它就是这样......

或者你可以使用setAccessible()来调用私有构造函数,但是你要打破单身人士并下地狱。

第三,你可以避免单独使用Singleton并找到更好的解决方案(通常有)。

答案 1 :(得分:8)

您可以使用反射来获取对类的静态工厂方法的引用,然后调用它。工厂方法可以强制执行单例模式

Class c = Class.forName("test.MyClass");
Method factoryMethod = c.getDeclaredMethod("getInstance");
Object singleton = factoryMethod.invoke(null, null);

然后

public class MyClass {

   private static MyClass instance;

   private MyClass() { 
      // private c'tor 
   }

   public static synchronized MyClass getInstance() {
      if (instance == null) {
         instance = new MyClass();
      }
      return instance:
   }
}

警告:单身人士设计模式可能对您的长期健康不利。

答案 2 :(得分:2)

您必须知道构造对象的单例类的方法名称。 如果它是例如称为“instance()”,您可以执行类似

的操作
Class c = Class.forName("MySingleton");
Method m = c.getDeclaredMethod("instance",null);
MySingleton singleton = m.invoke(null,null);

答案 3 :(得分:1)

您可以使用枚举并为每个枚举命名一个HashMap。或者你可以使用一些依赖注入框架来获取一些东西(Guice?)

编辑好的,我也加入了代码示例:

package tests;
public class EnumSingleton {
    public static void main(String[] args) throws Exception {
        Class<?> c = Class.forName("tests.Singleton1");
        Operation instance = Operation.class.cast(c.getEnumConstants()[0]);
        System.out.println(instance.getTHEAnswer());

        c = Class.forName("tests.Singleton2");
        instance = Operation.class.cast(c.getEnumConstants()[0]);
        System.out.println(instance.getTHEAnswer());
    }
}
interface Operation {
    int getTHEAnswer();
}
enum Singleton1 implements Operation {
    INSTANCE;
    @Override
    public int getTHEAnswer() {
        return 42;
    }
}
enum Singleton2 implements Operation {
    INSTANCE;
    @Override
    public int getTHEAnswer() {
        return 84;
    }
}

它安然无恙。 修改现在有一些意义。

答案 4 :(得分:0)

您是否可以依赖静态工厂方法的存在?它将依赖于某种方式的命名约定,但这可行。

底线:如果要知道一个类是单身,那么它必须对该监管负责。因此,它必须符合模式的某些实现,如果您想在这些类中进行动态选择,那么您需要能够预测“工厂”方法。