5

私は自分のプロジェクトでファクトリ クラスを作成しました。これにより、(理論的には) 任意の (サポートされている) 特定のタイプのマネージャーを作成できます。マネージャーとやり取りすることで、特定のタイプの特定のプロパティを変更できます。私が直面している問題は、ジェネリック型のマネージャーを作成しようとすると、コンパイラーが私の希望と夢を打ち砕くことです。

次のコードは、私が作業しているものの簡略化されたバージョンです。「test3Manager」を作成しようとした行がコンパイルされず、なぜそうなのかを理解しようとしています。その下の行は、回避しようとしている「回避策」を示しています。

    import java.util.List;

    public class GenTest {
        public static void main(String[] args) {
            String test1 = "";
            IRandomType<String> test2 = null;
            IAnotherRandomType<?> test3 = null;

            IManager<String> test1Manager = Factory.createManager(test1);
            IManager<IRandomType<String>> test2Manager = Factory.createManager(test2);
            IManager<IAnotherRandomType<?>> test3Manager = Factory.createManager(test3); // Doesn't compile. Why?

            // Work around?
            IManager<?> test3ManagerTmp = Factory.createManager(test3);
            IManager<IAnotherRandomType<?>> test3Manager2 = (IManager<IAnotherRandomType<?>>) test3ManagerTmp;
        }

        public interface IRandomType<T> {}
        public interface IAnotherRandomType<T> {}
        public interface IManager<T> {}

        public static class Factory {
            public static <T> IManager<T> createManager(T object) {
                return null;
            }
        }
    }

正確なコンパイル エラー メッセージは次のとおりです。

    Type mismatch: cannot convert from GenTest.IManager<GenTest.IAnotherRandomType<capture#1-of ?>> to GenTest.IManager<GenTest.IAnotherRandomType<?>>

以前にも同様の質問がありました (以下を参照)。ただし、この質問がそれらの重複と見なされるかどうかはわかりません。これらの質問から私の答えを推測するのに苦労しているので、私はこれを述べるだけです. ジェネリックの使用で私が間違っていることを誰かが明確にしてくれることを願っています。

SO に関する関連する質問は次のとおりです。

4

1 に答える 1

4

以下を使用します。

IManager<IAnotherRandomType<?>> test3Manager =
        Factory.<IAnotherRandomType<?>>createManager(test3);

これは、コンパイラの型推論が失敗した場合にすぎないため、 の型引数を明示的に指定する必要がありますT

より技術的に:

test3は型を持つように宣言されていますIAnotherRandomType<?>。ここ?で、 はワイルドカード キャプチャです。これは、特定の未知の型を表す一種の 1 回限りの型パラメーターです。それは、コンパイラが言うときに参照しているものcapture#1-of ?です。に渡すと、として推論されtest3ます。createManagerTIAnotherRandomType<capture#1-of ?>

一方、は、ネストされたワイルドカードtest3Managerを持つtype を持つと宣言されています。これは、型パラメーターのようには動作しませんが、任意の typeを表します。IManager<IAnotherRandomType<?>>

ジェネリックは共変ではないIManager<IAnotherRandomType<capture#1-of ?>>ため、コンパイラは からに変換できませんIManager<IAnotherRandomType<?>>

ネストされたワイルドカードの詳細:

于 2013-11-02T00:09:18.480 に答える