クレイジーJava講義ノート-第9章汎用型
28862 ワード
第9章汎用型
9.1汎用入門
9.1.1コンパイル時にタイプの異常をチェックしない
List list = new ArrayList();
list.add("abc");
list.add(3);
for(int i = 0; i < list.size(); i++) {
String str = (String) list.get(i); //(1)
}
コンテナに汎用型を付けず、コンテナからエレメントを取り出したときにタイプ変換を行う場合、(1)タイプ強制変換異常ClassCastExceptionを報告することがあります.
9.1.2手動によるコンパイル時のチェックタイプ
リストクラスラップArrayList追加addメソッドを作成し、メソッドパラメータに追加可能なタイプを追加します.弊害は、複数のListサブクラスを手動で作成することです.
9.1.3汎用型の使用
List<String> list = new ArrayList<>();
list.add("abc");
list.add(3); //(1)
括弧の中間タイプリストには、指定したタイプをStringとしてのみ装着でき、他のタイプを装着するとエラーが報告され、(1)コンパイラがエラーを報告します.
9.1.4 Java 7汎用型の「菱形」構文
List<String> list = new ArrayList<String>(); //(1)
List<String> list = new ArrayList<>(); //(2)
(1)はJava 7以前の表記,(2)はJava 7以降の表記である.
9.2深い汎用性
9.2.1汎用インタフェース、クラスの定義
public interface List<E> {
void add(E e);
...
}
public class Apple<T> {
private T info;
public Apple(T info) {
this.info = info;
}
public void setInfo(T info) {
this.info = info;
}
public T getInfo() {
return this.info;
}
public static void main(String[] args) {
Apple<String> apple = new Apple<>("abc");
}
}
上記の例では、汎用性のあるインタフェースとクラスをそれぞれ宣言し、使用時に汎用性Tを実際のタイプに変更すればよい.
9.2.2汎用系からの出産
汎用宣言のクラスまたはインタフェースから子または子インタフェースを割り当てる場合は、次のように、親汎用の特定のタイプを指定します.
public class A extends Apple<T> {
}
コンパイラがエラーを報告します.クラス、インタフェース、メソッドを定義するときにタイプパラメータを宣言します.クラス、インタフェース、メソッドを使用する場合は、タイプパラメータが実際のタイプに入力されるべきです(クラスまたはインタフェースは実際のタイプのパラメータに入力されません).Apple系から子系を派遣すると、次のコードに変更されます.
// Apple T String
public class A extends Apple<String> {
}
メソッドを呼び出すときは、すべてのデータパラメータ値を入力する必要があります.呼び出しメソッドとは異なり、クラス、インタフェースを使用するときに、実際のタイプパラメータを入力しないことができます.つまり、次のコードも正しいです.
public class A extends Apple
Appleから子クラスを派遣し,親メソッドを書き換える際には,汎用的な実際のタイプに注意し,メソッドの戻りタイプとパラメータは実際のタイプと一致しなければならない.
9.2.3汎用クラスは存在しない
Collection cs = nwe ArrayList<String>();
if(cs instanceof List<String>) {...} //
if(cs instanceof List) {...} //
9.3型ワイルドカード
public void test(List c) {
...
}
9.3.1タイプワイルドカードの使用
タイプワイルドカードは?要素タイプは、次のように任意のタイプに一致します.
public void test(List<?> c) {
...
}
c中の要素は常にObjectタイプであり、cはListであるため、List実行時にはObjectのみが保存され、汎用型はコンパイル期間中にコード提示作用を行うだけで、実際に実行時にはObjectが格納される.nullは、すべての参照タイプのインスタンスです.
9.3.2タイプワイルドカードの上限を設定する
Javaは、制限された汎用ワイルドカードを提供します.
public void drawAll(List<?> shapes) {
for(Object obj : shapes) {
//
Shape s = (Shape) obj;
s.draw();
...
}
}
// ? List Shape ( ),
public void drawAll(List<? extends Shape> shapes) {
// , Shape,
for(Shape s : shapes) {
s.draw();
...
}
shapes.add(0, new Rectangle()); // (1)
}
(1)ワイルドカードの上限はShapeだが?表示される実際のタイプが分からないので、オブジェクトを入れることはできません.
9.4汎用方法
9.4.1汎用メソッドの定義
static void fromArrayToCollection(Object[] a, Collection<Object> c) {
for(Object obj:a) {
c.add(obj);
}
}
以上の方法の限界は、Object配列の要素のみをObjectのCollectionコレクションにコピーでき、Collectionは使用できません.ワイルドカードCollection>を使用しても実行できません.オブジェクトを未知のタイプのコレクション(コレクション内の要素タイプが未知)に配置することはできません.この問題を解決するために、一般的な方法を導入し、文法フォーマットは以下の通りです.
<T, S> ( ) {
// ...
}
// :
static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
for(T o : a) {
c.add(o);
}
}
public static void main(String[] args) {
Integer[] ia = new Integer[100];
Collection<Number> cn = new ArrayList<>();
fromArrayToCollection(ia, cn);
}
汎用メソッドが呼び出されると、コンパイラは実パラメータに基づいてタイプパラメータの値を推定し、通常最も直接的なタイプパラメータを推定します.Integer[]iaはT[]aにTのタイプがIntegerであることを知らせる.
9.4.2汎用メソッドとタイプワイルドカードの違い
9.4.3 Java 7の「菱形」構文と汎用コンストラクタ
class Foo<E> {
public <T> Foo(T t) {
...
}
public static void main(String[] args) {
new Foo("abc");
new Foo(3);
new <String> Foo("abc");
new <String> Foo(3.2); // (1)
Foo<String> foo = new Foo<>(3); // E ,“abc” T
Foo<String> foo = new <Integer> Foo<String>(3); // T Integer,
Foo<String> foo = new <Integer> Foo<>(3); // (2) ,
}
}
(1)汎用コンストラクタにおけるTのパラメータはStringタイプであり,実際にはDoubleタイプ(2)汎用コンストラクタにおける汎用タイプがIntegerであることを明示的に指定すると菱形構文を用いてコンストラクタの後<>におけるクラスのEのタイプを省略することはできない.
9.4.4ワイルドカード下限設定
ワイルドカードの下限構文:super T>は、親の特定のタイプにかかわらず、子の特定のタイプにのみ関係し、ワイルドカードの下限を使用します.
9.4.5汎用方法と重荷
メソッドパラメータの汎用性に応じてメソッドの再ロードを許可しますが、呼び出し時にコンパイラがどのメソッドを呼び出すか分からない場合は、コンパイルエラー、(3)エラーを報告します.
public class MyUtils {
// (1)
public static <T> void copy(Collection<T> dest, Collection<? extends T> src) {...}
// (2)
public static <T> T copy(Collection<? super T> dest, Collection<T> src) {...}
public static void main(String[] args) {
List<Number> ln = new ArrayList<>();
List<Integer> li = new ArrayList<>();
copy(ln, li); // (3)
}
}