ジェネリックは、型を指定するために使用されます。
次のクラス定義を検討してください。
public interface List<E> extends Collection<E>
これは、任意の型の要素を保持できる List があることを示しています。
に制限がないことに注意してくださいE
。
次のようにクラスを定義すると:
public class MyList<T extends String> implements List<T>
String
これで、List を実装する MyList ができましたが、 s (または被相続人) のみを受け入れます。
このクラス内では、 を参照できますT
。
public class MyList<T extends String> implements List<T> {
private ArrayList<T> internalStorage;
重要なポイント
クラス定義では、定義されているものを定義しましたT
。String に基づく任意のクラスです。
したがって、クラス内で T を参照できます。
ただし、クラスが実際にインスタンス化されるまで、T のフレーバーは修正されません。
MyList<MyStringType> test = new MyList<MyStringType>(parameters); //java 6
MyList<MyStringType> test = new MyList<>(parameters); //java 7, same but shorter.
これで Javaは、クラス TT
内の意味MyList
が MyStringType であることを認識します。
知識を武器に、Java はクラスをコンパイルし、すべての参照をT
実際のクラスへの参照に置き換えますMyStringType
。
Tのことは完全に忘れている。
クラス内では、T
言及されているすべての箇所が MyStringType に置き換えられることに注意してください。
しかし、必ずしも MyStringType ではなく、文字列を処理したい場合はどうでしょう。
解決策:
次のようにメンバーを定義します。
List<? extends String> strs; //Will fill the data in later
これで、文字列のみを受け入れる strs という名前のリストができましたが、MyStringType 型の文字列の使用は強制されません。このリストは、がインスタンス化されたときに修正され
た の定義にバインドされていません。
に値を割り当てると、リストのフレーバーが修正されます。あなたの例では、文字列のリストになります。 T
MyList
strs
? extends String str;//error
変数を保持するクラスが作成されるときにその型を特定できないため、変数を修正できません。