なぜジェネリック医薬品を使うのか?
ジェネリックを使用していません:
// 创建列表类
List list = new ArrayList();
// 添加一个类型为 String 的列表元素
list.add("hello");
// 强制转换为 String 类型,再赋值给类型为 s 的引用变量
String s = (String) list.get(0);
ジェネリック医薬品の使用:
// 创建泛型类,<String> 为类型参数
List<String> list = new ArrayList<String>();
// 添加一个类型为 String 的列表元素
list.add("hello");
// 这里不需要强制类型转换
String s = list.get(0);
利点:コレクションの異なる種類の処理を、ユニバーサル汎用アルゴリズムを実現するには、タイプ、タイプセーフ、読みやすいをカスタマイズすることができます。
一般的なタイプ
ジェネリック型は、型パラメータ(<パラメータタイプ>)ジェネリッククラスまたはインタフェースです。
単純なBoxクラス
public class Box {
private Object object;
public void set(Object object) { this.object = object; }
public Object get() { return object; }
}
Boxクラスのメソッドを使用すると、任意のオブジェクトを渡すことができます基本的なタイプに加えて、オブジェクトを受け入れるか、または返します。整数整数に合格し、取得したいが、エラーに渡されたStringオブジェクトならば、それはコンパイル時に実行時エラーにつながるクラスが使用されているかチェックすることはできません。
Boxクラスジェネリック版
ジェネリック型定義フォーマット:
class name<T1, T2, ..., Tn> { /* ... */ } //T1, T2, ..., Tn为类型参数
クラス名の後ろ、角括弧内のパラメータのタイプ(<>)および(T1、T2、...、およびTN)を有するタイプのパラメータ(また、型変数としても知られています)、
改訂されたジェネリックBoxクラス:
/**
* Box 类的泛型版本
* @param <T> 类型的值被装箱
*/
public class Box<T> {
// T 表示 "类型"
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
任意のクラスの種類、任意のインタフェースタイプ、任意のタイプのアレイ、または変数であっても、任意の他のタイプ:上記のコードは、BoxクラスタイプがTで置き換えられているすべてのオブジェクトタイプは、変数は、非指定の基本的なタイプの任意のタイプであってもよいです。
一般的な技術は、共通の一般的なインタフェースを実現することができます。
型パラメータの命名規則
従来、単一の大文字と呼ばれるパラメータのタイプ。これは全く対照的で知られている変数の命名規則で、正当な理由でそれを行う:この合意がなければ、変数や通常のクラスまたはインタフェース名のタイプを区別することは困難です。
最も一般的なタイプのパラメータ名:
- E - (で広く使用される要素のJavaコレクション・フレームワーク)
- K - キー
- N - ナンバー
- T - タイプ
- V - バリュー
- S、U、Vなど - 第二、第三、第四のタイプ
電話してジェネリック型をインスタンス化
変数Tの別の種類の特定のタイプは、例えば、ジェネリック型をインスタンス化することができます。
Box <Integer> integerBox = new Box <Integer>();
呼び出しの一般的なタイプは、一般的に呼ばれ、「パラメータ化された型。」
いつものように使うnew
インスタンス化するキーワードを、しかし、クラス名と括弧の間に配置されました<Integer>
:
Java SE 7以降のリリースでは、限り、コンパイラは、パラメータのタイプを決定または推論することができるように、それはヌル型パラメータで設定することができる(<>)あるいは一般的なクラスのコンストラクタに必要なコンテキスト・パラメータに応じてタイプを呼び出します。例えば:
Box<Integer> integerBox = new Box<>();
マルチパラメータの型
ジェネリッククラスは、複数種類のパラメータを持つことができます。たとえば、ユニバーサルインターフェースOrderedPair一般的なクラスのペアを達成するために:
public interface Pair<K, V> {
public K getKey();
public V getValue();
}
public class OrderedPair<K, V> implements Pair<K, V> {
private K key;
private V value;
public OrderedPair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() { return key; }
public V getValue() { return value; }
}
次の文は、2つのインスタンスOrderedPairクラスを作成します。
Pair <String,Integer> p1 = new OrderedPair <String,Integer>(“Even”,8);
Pair <String,String> p2 = new OrderedPair <String,String>(“hello”,“world”);
新しいOrderedPair <String,Integer>
コードは、K、Vは整数としてインスタンス化された文字列としてインスタンス化されるであろう。したがって、パラメータ型コンストラクタOrderedPairそれぞれ文字列と整数。自動包装以来、およびクラスに渡された文字列intが効果的です。
上述したように、Javaコンパイラができるので、OrderedPair <String,Integer>
K及びV型宣言を推測、以下の略語を使用することが可能です。
OrderedPair <String,Integer> p1 = new OrderedPair <>(“Even”,8);
OrderedPair <String,String> p2 = new OrderedPair <>(“hello”,“world”);
パラメータ化されたタイプ
また、パラメータ化された型(すなわち一覧)(すなわち、KまたはV)のパラメータの種類を置き換えることができます。例えば、使用したOrderedPair <K,V>
例を:
OrderedPair <String,Box <Integer>> p = new OrderedPair <>(“primes”,new Box <Integer>(...));
プリミティブ型
これは、ジェネリッククラスまたはインタフェース名のいずれかのタイプなし元の型パラメータです。
例えば、一般的なクラスのボックスを与えられました:
public class Box<T> {
public void set(T t) { /* ... */ }
// ...
}
パラメータ化された型を作成するには、仮型パラメータTの実際の型パラメータを提供します。
Box<Integer> intBox = new Box<>();
実際の型パラメータが省略された場合、それが作成されますBox<T>
プリミティブ型を:
Box rawBox = new Box();
そのため、箱は一般的なものでありBox<T>
、プリミティブ型。しかし、非ジェネリッククラスまたはインタフェース型がプリミティブ型ではありません。
(そのようなコレクションクラスのような)多くの従来JDK5.0 APIの下位互換性を維持するために一般的ではない、それは元の型にパラメータ化されたタイプの割当てを可能にします。
Box<String> stringBox = new Box<>();
Box rawBox = stringBox; // OK
しかし、元の型がパラメータ化された型に割り当てられている、コンパイラは警告を発行します。
Box rawBox = new Box(); // rawBox 是 Box<T> 的原始类型
Box<Integer> intBox = rawBox; // warning: unchecked conversion
あなたは適切なジェネリック型で定義されている一般的なメソッドを呼び出すために元の型を使用する場合は、警告が表示されます:
Box<String> stringBox = new Box<>();
Box rawBox = stringBox;
rawBox.set(8); // warning: unchecked invocation to set(T)
警告は、型チェックの一般的なタイプは、危険なコードが実行時まで延期キャプチャしますオリジナルのバイパスを表示します。したがって、あなたは、プリミティブ型を使用しないでください。