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

enumを 1 つだけ持つINSTANCEなどの を作成します。インスタントシングルトン。

私があなたを正しく理解していれば、シングルトンに汎用インターフェースを実装してほしいと思いますか? 何かのようなもの:

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

その場合、未チェックのキャストを使用して、enum-as-singleton を一般化された方法で返すことができます。シングルトンが実際にインスタンスを使用しない限り、これは安全です (または、それがオブジェクトであると仮定するだけです)。

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そうしないと、他の誰かが自分の を使用しようとすると、ClassCastException が発生しますT。これは Foo と考えられますが、実際には単なるオブジェクトです。

于 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();

Tでは、 type の引数を受け取る場合、または 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 に答える