List<String> v = new ArrayList<String>();
ジェネリックは、ArrayList()がString型のオブジェクトを持っていることを宣言するのに役立つことを理解しています。私の質問は、次のものは上記とどのように違うのですか?
List<String> v = new ArrayList();
または他とは異なる以下のもの
List v = new ArrayList<String>();
List<String> v = new ArrayList();
これは実際には機能的に違いはありません。右側のtypeパラメーターは実際には何もしません。これはスタイルの問題として使用され、プログラミングエラーと見なされるRawタイプの使用を回避するために使用されます。実際、Java 7では拡張されているため、これを実行できますList<String> v = new ArrayList<>();
。右側で繰り返す必要はありません。
List v = new ArrayList<String>();
タイプパラメータのないリストは、Rawタイプと呼ばれます。ジェネリックスを使用している新しいコードでRaw型を宣言することは、一般にプログラミングエラーと見なされます。基本的に、このように宣言する場合、型チェックはまったく行われていません。そのリストには何でも入れることができます。
Javaジェネリックはコンパイル時のチェックです。したがって、重要なのはコンパイル時の参照のタイプです。参照がRaw型の場合List
、右側で何を宣言したかは関係ありません。これは、コンパイラーがチェックする対象です。
List<String>
実際には「文字列を含むリスト」ではありません。これは、「文字列以外のものをそこに入れると、エラーを返すか、警告するようにコンパイラに要求したリストです。コンパイラの警告を無視すると、そこにないものを取得することは完全に可能です」 t文字列。
public static void main(String[] args) throws Exception {
List<String> list1 = new ArrayList<String>();
List<String> list2 = new ArrayList(); //This is equivalent to list1 but with compilation warning
List list3 = new ArrayList<Integer>(); //This is equivalent to list3 = new ArrayList<Object>()
//list1.add(new Object()); //does not compile
//list2.add(new Object()); //does not compile
list3.add(new Object()); //this is fine
list1 = list3; //ok, but
System.out.println(list3.get(0)); // this is fine
System.out.println(list1.get(0)); //Runtime error: ClassCastException
//List<Object> list5 = list1; //does not compile
List<Object> list5 = list3; //ok
}
List v = new ArrayList();
これは、リストを宣言するJava5の方法の前です。
List<String> v = new ArrayList<String>();
これは、Java 5で導入されたジェネリックスを使用します。これにより、コンパイル時の型の安全性が追加されます。
List<String> v = new ArrayList<>();
これは、Java 7で導入された単なる最適化です。型の安全性を維持することにより、コードを単純化するだけです。
これらはすべてコンパイルされ、すべて有効です。2番目のケースでは、警告がスローされるだけである可能性があります。。が原因で文字列以外のものを追加することはできませんList<String>
。3番目のケースでは、反対の問題が発生します。文字列ではないものを追加できますが、結果として実行時例外が発生する可能性があります。
1番目と3番目のケース(new ArrayList<String>()
)では、インスタンスArrayList
を保持できるString
インスタンスをインスタンス化します
2番目のケース(new ArrayList()
)では、インスタンスArrayList
を保持できるインスタンスをインスタンス化しObject
ます(つまり、任意のタイプのインスタンス-混合して一致させることもできます)
1番目と2番目のケース( )では、インスタンスを保持できるインスタンスArrayList<String> v
を宣言しますArrayList
String
3番目のケース( )では、のインスタンスを保持できるArrayList v
のインスタンスを宣言します。ArrayList
Object
2番目のケースの問題は、「生の」ArrayList
(インスタンス化されたもののような)を取得した場合、理論的には何でも保持できることです。インスタンスだけString
でなく、宣言のユーザーが期待するものです。
同様に、3番目のケースでは、 sArrayList
を保持することになっているを作成String
しますが、宣言のユーザーはそれを知らず、他のオブジェクトインスタンスをその中に入れようとする可能性があります
注:もちろん、内部では、JVMではジェネリック型の情報が失われるため、実行の点で違いはありませんが、プログラミング型の安全性のために、コンパイラーは誤った使用にフラグを立てます。このように、リストに入れられる/リストから出てくるオブジェクトのタイプを動的にチェック/確認する必要はありません-コンパイラがこれを保証したので、それらが正しいタイプであるとみなすことができます