有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

单例引用的Java映射

我想创建一个单例类的映射,我可以通过交叉引用来访问它,以便响应特定的请求。我实现了以下内容,但在获取可以调用getInstance()的实际引用时遇到了困难

Map<Integer, Class<? extends Thing>> xref = new HashMap<Integer, Class<? extends Thing>>();
xref.put(1, ThingOne.class);
xref.put(2, ThingTwo.class);

Class<? extends Thing> t = xref.get(1);

最后,做一些类似于

something.perform(arg1, arg2);

我不知道如何从“t”到“某物”,或者根据我的编码方式,这是可能的。我试着打电话。铸造(东西类)。getInstance(),但发生强制转换异常。还尝试了反射来获取getInstance()方法,但也没有成功

也许我走错了路。给定1。。n个可能的函数,解决方案的任何给定实例可能只需要其中的一个子集。此外,我希望通过配置轻松添加/删除类并管理接口,而不是在启动时通过一系列对象实例化

谢谢


共 (1) 个答案

  1. # 1 楼答案

    我不太明白你制作这张地图的目的。从您所写的内容来看,似乎可以简单地将返回单例的静态getInstance()方法放在每个相关类上。或者更简单:将每个共享实例作为其类的静态最终字段

    如果必须使用映射,请不要使用整数作为键。类是键,其实例是值。比如:

    private static final Map<Class<?>,Object> singletons = new HashMap<>();
    
    public static synchronized <T> T getSingleton(Class<T> klass) {
        Object obj = singletons.get(klass);
        if (obj == null) {
            try {
                obj = klass.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
            singletons.put(klass, obj);
        }
        return klass.cast(obj);
    }
    

    那里的创建代码很恶心,需要一个公共的无参数构造函数。您也可以通过反射在每个类上调用一个静态的、专门命名的方法来创建所需的实例(“createInstance”),这可能会更灵活一些,但当您这样做时,它再次询问,既然您可以直接在类上调用一个方法,为什么还要麻烦映射

    映射的一个有趣的可能性是提供创建实例的函数。在Java 8语法中(导入java.util.function.Supplier):

    private static final Map<Class<?>,Object> singletons = new HashMap<>();
    
    public static synchronized <T> T getSingleton(Class<T> klass) {
        Object obj = singletons.get(klass);
        if (obj instanceof Supplier) {
            obj = ((Supplier<?>)obj).get();
            singletons.put(klass, obj);
        }
        return klass.cast(obj);
    }
    
    public static synchronized <T> void declareSingleton(Class<T> klass, Supplier<T> supplier) {
        if (Supplier.class.isAssignableFrom(klass)) {
            // prevent Supplier<Supplier<?>> weirdness;
            // could use separate maps if those are really needed
            throw new UnsupportedOperationException();
        }
        singletons.put(klass, supplier);
    }
    
    static {
        // add creation expressions for several classes;
        // instances will not be created until needed
        declareSingleton(ThingOne.class, () -> new ThingOne());
        declareSingleton(ThingTwo.class, () -> new ThingTwo(123));
    }
    

    我不确定这是否是你想要的,但它可能包含一些想法

    编辑:我刚刚意识到将类本身用作键的问题:它会导致类被加载,即使在特定程序运行期间不需要它。使用字符串键可以避免加载不需要的类,但会增加脆弱性。这是另一个反对使用地图的论点