これら2つの宣言の違いは何ですか?
宣言1:
ArrayList<String> arrayList = new ArrayList<String>();
宣言2:
List<String> arrayList = new ArrayList<String>();
List<String> arrayList = new ArrayList<String>();
実装の詳細を非表示にしてクライアントに返す場合は一般的です。後で、実装をArrayList
からLinkedList
透過的に変更できます。
このメカニズムは、クライアント側での最小限の変更で、ある時点で実装の詳細を変更する可能性のあるライブラリなどを設計する場合に役立ちます。
ArrayList<String> arrayList = new ArrayList<String>();
これにより、常に戻る必要がありますArrayList
。ある時点で、実装の詳細をに変更したい場合はLinkedList
、クライアント側でも。LinkedList
の代わりに使用するように変更する必要がありArrayList
ます。
List
はインターフェイスでArrayList
あり、Listインターフェイスの実装です。このArrayList
クラスには(i.e clone(), trimToSize(), removeRange() and ensureCapacity())
、リストインターフェイスで使用可能なメソッドに加えて、いくつかのメソッドしかありません。これには大きな違いはありません。
1. List<String> l = new ArrayList<>();
2. ArrayList<String> l = new ArrayList<>();
最初のものを使用すると、リストインターフェイスで使用可能なメソッドを呼び出すことができ、ArrayList
クラスで使用可能な新しいメソッドを呼び出すことはできません。一方、2番目のメソッドを使用する場合は、で使用可能なすべてのメソッドを自由に使用できますArrayList
。
Javaアプリケーションを開発しているとき、コレクションフレームワークオブジェクトをメソッドへの引数として渡すことになっているときは、最初のアプローチを使用する方がよいため、最初のアプローチの方が優れていると思います。
List<String> l = new ArrayList<>();
doSomething(l);
将来、パフォーマンスの制約により、使用するように実装を変更する場合、またはの代わりにインターフェイスLinkedList
を実装する他のクラスを変更する場合は、1つのポイント(インスタンス化部分)でのみ変更する必要があります。List
ArrayList
List<String> l = new LinkedList<>();
それ以外の場合は、メソッド引数として特定のクラス実装を使用した場所を問わず、すべての場所で変更する必要があります。
違いは、バリアント1は強制的に使用するのArrayList
に対し、バリアント2はを実装するものがあることを保証するだけであるということですList<String>
。
後で、List<String> arrayList = new LinkedList<String>();
それほど面倒なことなくそれを変更することができます。バリアント1では、の操作に依存している場合は、その行だけでなく他の部分も変更する必要がある場合がありますArrayList<String>
。
したがって、提供List<String>
する追加のメソッドを呼び出す必要がある場合を除いて、ほとんどすべての場合に使用しArrayList
ます(これまでのところそうではありませんでした):ensureCapacity(int)
およびtrimToSize()
。
最初の宣言はArrayListである必要があり、2番目の宣言は別のリストタイプに簡単に変更できます。そのため、特定の実装を必要としないことが明確になるため、2番目が推奨されます。(実際に1つの実装が必要な場合もありますが、それはまれです)
List
実装をSet
次のように変更するのは簡単です。
Collection<String> stringList = new ArrayList<String>();
//Client side
stringList = new LinkedList<String>();
stringList = new HashSet<String>();
//stringList = new HashSet<>(); java 1.7 and 1.8
基本的に、Javaは、Javaの主な機能の1つであるジェネリック型宣言(のような)によって、1つの構造体実装に複数の型オブジェクトを格納できclass MyStructure<T extends TT>
ます。
オブジェクト指向のアプローチは、関心の分離によるモジュール性と再利用性に基づいています。つまり、あらゆる種類のオブジェクトで構造を使用する機能です(いくつかのルールに従っている限り)。
次のようにインスタンス化することができます。
ArrayList list = new ArrayList();
それ以外の
ArrayList<String> list = new ArrayList<>();
ジェネリック型を宣言して使用することにより、管理するオブジェクトの種類を構造体に通知します。たとえば、コンパイラーは、その構造体に不正な型を挿入しているかどうかを通知できます。まあ言ってみれば:
// this works
List list1 = new ArrayList();
list1.add(1);
list1.add("one");
// does not work
List<String> list2 = new ArrayList<>();
list2.add(1); // compiler error here
list2.add("one");
いくつかの例を見たい場合は、ドキュメントのドキュメントを確認してください。
/**
* Generic version of the Box class.
* @param <T> the type of the value being boxed
*/
public class Box<T> {
// T stands for "Type"
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
次に、次のようなものをインスタンス化できます。
class Paper { ... }
class Tissue { ... }
// ...
Box<Paper> boxOfPaper = new Box<>();
boxOfPaper.set(new Paper(...));
Box<Tissue> boxOfTissues = new Box<>();
boxOfTissues.set(new Tissue(...));
これから引き出す主なことは、ボックス化するオブジェクトのタイプを指定することです。
の使用に関しては、または実装にObject l = new ArrayList<>();
アクセスしていないため、コレクションで多くのことを行うことはできません。List
ArrayList
おそらく、このリンクhttp://docs.oracle.com/javase/6/docs/api/java/util/List.htmlを参照でき ます。
Listはインターフェイスです。ArrayList、LinkedListなどはlistを実装するクラスです。ListInterfaceを使用する場合は、ListIteratorを使用して要素を反復し、リスト内で前後に移動できます。ArrayListの場合と同様に、Iteratorを使用して反復します。一方向にアクセスしました。
Listはインターフェースであり、ArrayListは具象クラスで実装されています。常に使用することをお勧めします。
List<String> arrayList = new ArrayList<String>();
ここでリスト参照は柔軟だからです。オブジェクトを保持することもできLinkedList or Vector
ます。
たとえば、JITコンパイラを使用しない一部のJVMでは、パフォーマンスを(わずかに)向上させるために最初の状況を好む場合がいくつかあります。
そのような非常に特殊なコンテキストから、最初のものを使用する必要があります。
GuavaのようなオープンソースコミュニティやGoogleDeveloper(Android Library)からのコーディングを見たときはいつでも、彼らはこのアプローチを使用しました
List<String> strings = new ArrayList<String>();
実装の詳細をユーザーから隠すためです。あなたは正確に
List<String> strings = new ArrayList<String>();
それは一般的なアプローチであり、この特殊なアプローチです
ArrayList<String> strings = new ArrayList<String>();
参照用:Effective Java 2nd Edition:Item 52:インターフェースでオブジェクトを参照する