3

私は Java ジェネリックに関して少し奇妙な問題を抱えています。実際にはまったく問題にならないかもしれませんし、設計でジェネリックを間違って使用しようとしているのは私だけかもしれません。申請書の詳細はすべてお伝えしません (無関係で退屈です)。

問題の本質を捉えた小さなスニペットを作成しました。

このような Producer インターフェイスがあります。

public interface Producer<P> {
public P produce(); 
}

このように見えるこのインターフェースの実装があります

public class IntegerProducer<P> implements Producer<P> {

@Override
public P produce() {
    return (P)new Integer(10);
}
}

私がプロデュースメソッドで本当にする必要があるのは、次のようなものです

if (P instanceOf Integer) return (P)new Integer(10);
else throw new Exception("Something weird happened in the client app"); 

もちろん、P instanceOf Integer は機能しません。しかし、私がやろうとしていることの本質を理解している場合は、解決策を共有してください.

助けてくれてありがとう。

明確化 1: 問題は、整数のみを返したいということではありません。問題は、関数 Produce() で、クライアント プログラムが使用するジェネリックの型を確認し、それに基づいて関数の動作を変更する必要があることです。特定のタイプのオブジェクト (ワイルドカードを使用できた場合) に使用されるジェネリックのタイプを制限したいということではありませんが、ジェネリックで使用されるオブジェクトの種類に基づいて、関数 Produce() の動作が少し異なる必要があります。クライアントコード。

4

1 に答える 1

10

どうですか:

public class IntegerProducer implements Producer<Integer> {

    @Override
    public Integer produce() {
        return 10;
    }
}

IntegerProducers のみを扱うため、Integer一般的である必要はありません。次に、次のように記述できます。

Producer<Integer> p = new IntegerProducer();
Integer i = p.produce();

編集

あなたのコメントに従って、唯一の方法はクラスパラメーターを渡すことだと思います:

public class Producer<T> {

    public static void main(String[] args) throws InterruptedException {
        Producer<Integer> t1 = new Producer<> ();
        Producer<String> t2 = new Producer<> ();
        System.out.println(t1.get(Integer.class)); //prints 10
        System.out.println(t1.get(String.class)); //does not compile
        System.out.println(t2.get(String.class)); //throws exception
    }

    public T get(Class<T> c) {
        if (c == Integer.class) {
            return (T) (Object) 10;
        }
        throw new UnsupportedOperationException();
    }
}

または、コンストラクターで渡すこともできます (たとえば、EnumSets および EnumMaps で使用される戦略)。

public class Producer<T> {

    public static void main(String[] args) throws InterruptedException {
        Producer<Integer> t1 = new Producer<> (Integer.class);
        Producer<Integer> t1 = new Producer<> (String.class); //does not compile
        Producer<String> t2 = new Producer<> (String.class);
        System.out.println(t1.get()); //prints 10
        System.out.println(t2.get()); //throws exception
    }

    private final Class<T> c;

    public Producer(Class<T> c) {
        this.c = c;
    }

    public T get() {
        if (c == Integer.class) {
            return (T) (Object) 10;
        }
        throw new UnsupportedOperationException();
    }
}

それは明らかにコードを乱雑にするので、私は個人的にそのような状況を避けるために設計を再考します.

于 2013-01-04T10:56:32.060 に答える