6

我想在 java 中创建一个通用的单例类,女巫给出了我传入方法参数的类的单例对象。类似下面的代码:请帮助

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

5 回答 5

7

只使用一个enumINSTANCE或类似的值。即时单例。

如果我理解正确,我认为您希望您的单例实现一些通用接口?就像是:

interface ListenerInterface<T> {
    void handleEvent(T event);
}

在这种情况下,您可以使用未经检查的强制转换以通用方式返回您的枚举作为单例。只要您的单例实际上不使用该实例(或者,只假设它是一个对象),这是安全的。

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);
    }

}

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

于 2012-08-02T06:50:20.790 回答
3

这将是评论,但由于字符限制,我认为最好是一个答案,

稍微深入思考一下,真的有可能创建一个通用的单例类吗?

单例类不能被实例化,也不应该被克隆。

要给任何班级这种行为,你必须做出all the constructors private and clone method will have to be overridden to throw an exception. 现在,如果您要更改所有类以实现此行为,那么您创建单例的方式真的是通用的吗?

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

于 2012-08-02T07:05:10.107 回答
1

你可以做这样的事情,但恕我直言不可靠:

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

}

于 2012-08-02T07:34:29.350 回答
1

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

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
    }
}
于 2016-12-28T12:01:37.127 回答
0

我不确定我是否完全理解您的问题,但是如果您想将单例集成到通用层次结构中,您必须作弊(就像我们在本主题中所做的那样):

interface Listener<T>{
    // ...
}

@SuppressWarnings("unchecked")
final class SingletonListener {

    private SingletonListener() {
        assert false : "Uninstantiable";
    }

    public static <T> Listener<T> instance() {
        return SingletonListenerInstance.INSTANCE;
    }

    // Note - implements Listener without specifying type parameters!
    private enum SingletonListenerInstance implements Listener {
        INSTANCE;
        // Insert listener methods here
    }
}


// Usage:
Listener<Pony> ponyListener = SingletonListener.instance();

那么如果这个实现接收到 type 的参数T,或者期望返回 type 的(或相关的)值,它会做什么T呢?好吧,不多,但比没有更重要!这是一个带有示例实现的更充实的版本:

interface Listener<T> {
    void receive(T something);

    T process(T something);

    T produce();

    List<T> produceMany();
}

@SuppressWarnings("unchecked")
final class SingletonListener {

    private SingletonListener() {
        assert false : "Uninstantiable";
    }

    public static <T> Listener<T> instance() {
        return SingletonListenerInstance.INSTANCE;
    }

    // Note - implements Listener without specifying type parameters!
    private enum SingletonListenerInstance implements Listener {
        INSTANCE;
        // Insert listener methods here

        @Override
        public void receive(Object something) {
            // We can log what we receive because we know everything is an Object
            // and so has a toString method; we can also use other Object methods,
            // do reflection (or just ignore it and leave a no-op implementation)
            System.out.println("Received " + something);
        }

        @Override
        public Object process(Object something) {
            // We can return something we know to be of the right type, which in our
            // case typically is arguments we've received
            return something;
        }

        @Override
        public Object produce() {
            // Null is a valid value for all types
            return null;
        }

        @Override
        public List produceMany() {
            // Don't need any instances of the generic type to create an empty list
            return Collections.EMPTY_LIST;
        }
    }
}
于 2012-08-02T07:01:01.567 回答