3

メソッドの出力に対して完全にジェネリックな型を宣言するのに問題があります。状況は次のとおりです。

class A<S,T>{
public Callback<B<S,T>,C<S,T>> method();
}

私のコードでは、これらのいずれかを持っています。

A<String, ?> instance;

しかし、私が電話するとき

result = instance.method()

コンパイラを満足させる唯一の方法は、宣言することです

Callback<?, ?> result = instance.method()

しかし、ジェネリックをより具体的にして宣言したいと思います

Callback<B<String, ?>,C<String, ?>> result = instance.method()

ただし、各ワイルドカードは個別であるため、コンパイラはこれが正しくないことを訴え、ワイルドカードから変換できないことを示します。

Callback<B<String,capture#3-of ?>,C<String,capture#3-of ?>>

この状況を正しく宣言する方法はありますか?

参考までに、クラス A、B、および C は外部ライブラリからのものです。インスタンスを次のように宣言しようとしました

A<String, Object>

しかし、それは私が制御できない 4 番目のクラスのメソッドの結果でもあります。

class D<T>{
public A<T, ?> getObject();
}

D<String> start = new D<String>();
A<String, ?> = start.getObject();
...
4

2 に答える 2

1

あなたが持っている可能性があります

Callback<? extends B<String, ?>, ? extends C<String, ?>> result
    = instance.method();
于 2013-03-01T04:17:42.907 に答える
1

これは実に厄介な状況です。ワイルドカード キャプチャの制限と からの戻り値の型が理想的ではないためD.getObjectです。

いくつかの回避策がありますが、どれもきれいではありません。1 つ目は、単純に未チェックのキャストを行うことです。

@SuppressWarnings("unchecked") //it's okay for the two captures not to match
Callback<B<String, ?>, C<String, ?>> result =
        (Callback<B<String, ?>, C<String, ?>>)instance.method();

EDIT:一部のコンパイラは(より正確には)次のダブルキャストを必要としますCallback<?, ?>

@SuppressWarnings("unchecked") //it's okay for the two captures not to match
Callback<B<String, ?>, C<String, ?>> result =
        (Callback<B<String, ?>, C<String, ?>>)(Callback<?, ?>)instance.method();

ヘルパー メソッドを使用することもできます。これは、ワイルドカード キャプチャの問題に対する一般的な解決策です。

static <T> void helper(A<String, T> a) {

    Callback<B<String, T>, C<String, T>> result = a.method();

    //logic
}

...

helper(instance);

アップデート:

実際、これら 2 つのアプローチを組み合わせて、少なくとも醜さを 1 つのヘルパー メソッドに分離することができます。

static <S, T> Callback<B<S, ?>, C<S, ?>> disentangleCallback(
        Callback<B<S, T>, C<S, T>> callback
) {
    @SuppressWarnings("unchecked") //it's okay for the two captures not to match
    final Callback<B<S, ?>, C<S, ?>> withWidenedTypes =
            (Callback<B<S, ?>, C<S, ?>>)(Callback<?, ?>)callback;
    return withWidenedTypes;
}

そして、次のように使用します。

Callback<B<String, ?>, C<String, ?>> result =
        disentangleCallback(instance.method());

または、単純に を取り、それ自体を呼び出してからキャストすることA<S, T>で を返す同様のメソッド。Callback<B<S, ?>, C<S, ?>>method


別のアイデア: の 2 番目の型引数A常に不明である場合は、それを削除して の戻り値の型を広げる方が簡単かもしれませんmethod

class A<S> {
    public Callback<B<S, ?>, C<S, ?>> method() { ... }
}

Tそれは残念な譲歩であることは承知していますが、実際には役に立たない場合は理にかなっています。

于 2013-03-01T04:17:46.337 に答える