Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在java中创建通用的单例类?_Java_Generics - Fatal编程技术网

如何在java中创建通用的单例类?

如何在java中创建通用的单例类?,java,generics,Java,Generics,我想在java中创建一个通用的singleton类,它提供我传入方法参数的类的singleton对象。下面的代码:请帮助 public final class Listener<T extends Object> { private Listener() { } public static <T> Listener<?> getInstance(Class<T> clazz) { return Singl

我想在java中创建一个通用的singleton类,它提供我传入方法参数的类的singleton对象。下面的代码:请帮助

public final class Listener<T extends Object>  {
    private Listener() {
    }

    public static <T> Listener<?> getInstance(Class<T> clazz) {
        return SingletonHolder.INSTANCE;
    }

    private static class SingletonHolder {
        public static final Listener INSTANCE = new Listener();
        // private static final Map<Class<? extends Runnable>,Listener<? extends
        // Runnable> INSTANCE = new ...;
    }
}
公共最终类侦听器{
私有侦听器(){
}
公共静态侦听器getInstance(类clazz){
返回SingletonHolder.INSTANCE;
}
私有静态类单音持有人{
公共静态最终侦听器实例=新侦听器();

//私有静态最终映射仅使用一个值创建一个
enum
INSTANCE
或类似值。即时单例

如果我理解正确,我认为您希望您的singleton实现一些通用接口,比如:

interface ListenerInterface<T> {
    void handleEvent(T event);
}
接口监听器接口{
无效处理事件(T事件);
}
在这种情况下,您可以使用未经检查的强制转换以一般化的方式将枚举返回为singleton。这是安全的,只要您的singleton不实际使用实例(或者只假设它是一个对象)

公共枚举MySingleton实现ListenerInterface{ 实例; @抑制警告(“未选中”) 公共静态ListenerInterface getListener(){ 返回(ListenerInterface)实例; } 公共无效handleEvent(对象事件){ System.out.println(“我是一个单身汉,发生了一件事:“+event”); } }

如果接口是生产者而不是消费者——也就是说,它返回一个
T
——那么您只能安全地返回
null
。否则,其他人在尝试使用
T
时会得到ClassCastException,他们认为这是一个Foo,但实际上只是一个对象。

我不确定是否理解您的问题完全启用,但如果您想将单例集成到通用层次结构中,则必须进行一些欺骗(就像我们在中所做的那样):

public enum MySingleton implements ListenerInterface<Object> {
    INSTANCE;

    @SuppressWarnings("unchecked")
    public static <T> ListenerInterface<T> getListener() {
        return (ListenerInterface<T>) INSTANCE;
    }

    public void handleEvent(Object event) {
        System.out.println("I am a singleton. An event happened: " + event);
    }

}

这将是一个评论,但我认为最好是一个答案,因为角色限制

再深入一点思考,是否真的有可能创建一个通用的单例类

不能实例化单例类,也不应克隆它

要使任何类具有这种行为,您必须使所有构造函数都成为私有的,并且必须重写clone方法以引发异常。现在,如果您要更改所有类以实现这种行为,那么您创建singleton的方法真的是通用的吗


请原谅,如果我错误地解释了这个问题

你可以这样做,但这是不可靠的

public class SimpleSingleton {
private Map<String, Object> counter = new HashMap<String, Object>();

public <T> T getInstance(Class<T> clazz) throws IllegalAccessException, InstantiationException {
    T singleton = (T) counter.get(clazz.getName());
    if (singleton == null) {
        singleton = clazz.newInstance();
        counter.put(clazz.getName(), singleton);
    }
    return singleton;
}
公共类SimpleSingleton{
私有映射计数器=新HashMap();
public T getInstance(类clazz)抛出IllegalacessException、InstanceionException{
T singleton=(T)counter.get(clazz.getName());
if(singleton==null){
singleton=clazz.newInstance();
counter.put(clazz.getName(),singleton);
}
返回单身;
}

}

我对这个问题的解决方案是这样设计:

public interface IListener<T extends Object>  {
    void handle(T event);
}

public final class Listener implements IListener<Object> {
    private static Listener instance = new Listener();

    private Listener() {
    }

    public static Listener getInstance() {
        return instance;
    }

    @Override
    public void handle(Object event) {
        //TODO Do stuff
    }
}
公共接口浏览器{
无效句柄(T事件);
}
公共最终类侦听器实现IListener{
私有静态侦听器实例=新侦听器();
私有侦听器(){
}
公共静态侦听器getInstance(){
返回实例;
}
@凌驾
公共无效句柄(对象事件){
//待办事项
}
}

为什么您需要它是泛型的?在您的示例中,您没有以任何方式使用T。它可能是有用的。这难道不会违反singleton所基于的整个概念(只有该类的一个实例)吗?您到底想要实现什么?如果它是一个真正的单例,它就不能是真正的泛型,因为您必须在创建时选择类型参数。或者您希望每个T类型有一个实例吗?顺便说一句,一个泛型单例肯定是有意义的——只要它不接受或给出其泛型参数的实例。
Collections.empty[List | Map | Set]()
返回单例实例,如果您尝试添加或获取任何元素,这些实例将失败。
emptyList
(etc)方法具有未选中的强制转换,以将单例转换为
列表
(与其他集合接口相同).+1,我也不明白为什么会有向下投票,这是一个琐碎、简单、好的解决方案,这里还有一个很好的链接,用于讨论枚举是一个单例实现,不应该是最后一个类SingletonListener吗{?此代码不会编译,即使您对其进行了修改,它也不会与包含具有泛型参数或返回类型的方法的侦听器一起工作。因此,它只与侦听器一起工作,而不会与侦听器一起工作。它不是泛型解决方案。@user1677663感谢您指出不可编译性,修复了这一问题。至于这些方法可以实现什么n do,事实证明,您实际上可以做一些事情!当然,对于虚拟/无操作的实现来说,大多数都是有用的,您必须跟踪什么是什么,否则您将在客户端代码中出现令人惊讶的
ClassCastException
s,但是可以设想一些有用的情况。感谢您将其充实到人们可以看到的程度他们用这种方法到底在干什么!
public class SimpleSingleton {
private Map<String, Object> counter = new HashMap<String, Object>();

public <T> T getInstance(Class<T> clazz) throws IllegalAccessException, InstantiationException {
    T singleton = (T) counter.get(clazz.getName());
    if (singleton == null) {
        singleton = clazz.newInstance();
        counter.put(clazz.getName(), singleton);
    }
    return singleton;
}
public interface IListener<T extends Object>  {
    void handle(T event);
}

public final class Listener implements IListener<Object> {
    private static Listener instance = new Listener();

    private Listener() {
    }

    public static Listener getInstance() {
        return instance;
    }

    @Override
    public void handle(Object event) {
        //TODO Do stuff
    }
}