web-dev-qa-db-ja.com

Java汎用フィールド宣言

ジェネリック型のないクラスでは、次のような複雑なジェネリックフィールドを宣言します。

public class Client {
    private Map<Class<T extends Serializable>, List<Consumer<S extends T>>> classToConsumerTry1;

    private <T extends Serializable, S extends T> Map<Class<T>, List<Consumer<S>>> classToConsumerTry2;
}

問題はJavaコンパイラーが私にさせてくれません:)

したがって、私の質問は、クラスClientに型を追加せずにTとSを正しく導入する方法です。

私の目標は、ClassSerializableのサブタイプとし、ConsumerClassに対して選択したクラスのサブタイプにすることです。

11
succcubbus

できません。唯一の選択肢は、Clientクラス宣言でジェネリック型パラメーターを宣言することです。 Clientクラスにジェネリック型パラメーターがない場合、そのメンバーをジェネリックにすることはできません。クラスメンバーの宣言では、実際の型を使用する必要があります。

10
Eran

クラスメンバーの定義でそれらを使用できるように、どこかに型パラメーターを導入する必要があります。

型パラメーターの導入は、クラスレベルまたはメソッドレベルでのみ実行できます。あなたの場合、それはクラスレベルでなければなりません:

public class Client<T extends Serializable, S extends T> {
    private Map<Class<T>, List<Consumer<S>>> classToConsumerTry1;

    private Map<Class<T>, List<Consumer<S>>> classToConsumerTry2;
}

ただし、これは両方のメンバー(classToConsumerTry1およびclassToConsumerTry2)、TおよびSは同じです。それらを異なるものにしたい場合は、これらの2つの値を2つの異なるクラスから取得する必要があります。これらのクラスは両方とも、別個の型パラメーターでパラメーター化されています。

4

フィールドで直接実行することはできませんが、ジェネリックメソッドによって型ポリシーを維持できます(ジェネリック以外のクラスにも存在できます)。

@SuppressWarnings("rawtypes")
private Map<Class, List> map;

public <T extends Serializable> void put(Class<T> key, List<Consumer<? extends T>> value) {
    map.put(key, value);
}

@SuppressWarnings("unchecked")
public <T extends Serializable> List<Consumer<? extends T>> get(Class<T> key) {
    return map.get(key);
}
4
Philip Voronov

思い通りのやり方はできません。ただし、Objectとして設定してキャストできます。その他のハックな答えには、Listの_<? extends Serializable>_の使用が含まれます(ただし、これは1つのextendsに対してのみ機能します)。次に、add()アイテムまたは何かを実行する内部クラスお気に入り:

_private class Foo<T> {
        T obj;
}
_

したがって、内部でobjにアクセス/変更できます。

1
AllDayAmazing