[〜#〜] pmd [〜#〜] は次の違反を報告します:
ArrayList<Object> list = new ArrayList<Object>();
違反は、「「ArrayList」などの実装タイプの使用を避け、代わりにインターフェースを使用する」でした。
次の行は違反を修正します。
List<Object> list = new ArrayList<Object>();
なぜList
の代わりにArrayList
を使用するのですか?
具象型でインターフェースを使用することは、適切なカプセル化とコードの疎結合の鍵となります。
独自のAPIを作成する場合は、この方法に従うことをお勧めします。そうすると、後でユニットテストを(モッキングテクニックを使用して)コードに追加する方が簡単で、将来的に必要に応じて基本となる実装を変更する方が簡単です。
これが 良い記事 です。
それが役に立てば幸い!
リストの実装からコードを分離するので、これが推奨されます。インターフェースを使用すると、実装(この場合はArrayList)を別のリスト実装に簡単に変更できます。リストで定義されたメソッドのみを使用している限り、コードの残りの部分を変更する必要はありません。
一般に、インターフェースを実装から分離することは良いことであり、コードの保守が容易になることに同意します。
ただし、考慮しなければならない例外があります。インターフェイスを介してオブジェクトにアクセスすると、間接層が追加され、コードが遅くなります。
興味深いことに、100万長のArrayListへの100億の順次アクセスを生成する実験を実行しました。私の2.4Ghz MacBookでは、Listインターフェイスを介してArrayListにアクセスするのに平均で2.10秒かかりました。タイプがArrayListであると宣言すると、平均で1.67秒かかりました。
大きなリストを処理している場合、内部ループの深部、または頻繁に呼び出される関数の場合は、これを考慮する必要があります。
ArrayListとLinkedListは、項目の順序付けられたコレクションであるリストの2つの実装です。論理的には、ArrayListとLinkedListのどちらを使用するかは問題ではないため、型をそのように制約しないでください。
これは、たとえば、コレクションとリストという異なるものとは対照的です(リストはソートを意味し、コレクションはそうではありません)。
ArrayListの代わりに後者をListと共に使用する必要があるのはなぜですか?
それは良い習慣です:実装ではなくインターフェイスするプログラム
ArrayList
をList
に置き換えることで、ビジネスユースケースに応じて、以下のようにList
の実装を将来変更することができます。
List<Object> list = new LinkedList<Object>();
/* Doubly-linked list implementation of the List and Deque interfaces.
Implements all optional list operations, and permits all elements (including null).*/
OR
List<Object> list = new CopyOnWriteArrayList<Object>();
/* A thread-safe variant of ArrayList in which all mutative operations
(add, set, and so on) are implemented by making a fresh copy of the underlying array.*/
OR
List<Object> list = new Stack<Object>();
/* The Stack class represents a last-in-first-out (LIFO) stack of objects.*/
OR
その他のList
固有の実装。
List
インターフェイスはコントラクトを定義し、List
の特定の実装は変更できます。このようにして、インターフェースと実装は疎結合されます。
関連するSEの質問:
クラス/インターフェースのプロパティは、実装に関係なく、使用する動作の規約をクラスに提供するため、インターフェースを通じて公開する必要があります。
しかしながら...
ローカル変数宣言では、これを行うことはほとんど意味がありません。
public void someMethod() {
List theList = new ArrayList();
//do stuff with the list
}
ローカル変数の場合は、型を使用します。それは依然として適切なインターフェースに暗黙的にアップキャスト可能であり、メソッドはその引数のインターフェース型を受け入れると期待されますが、ローカル変数の場合、実装が必要な場合に備えて、実装型をコンテナーとして使用することは完全に理にかなっています。特定の機能。
ローカル変数の場合でも、具象クラスでインターフェースを使用すると役立ちます。インターフェースの外にあるメソッドを呼び出すことになる場合があり、必要に応じてリストの実装を変更することは困難です。また、宣言では、最も特定度の低いクラスまたはインターフェイスを使用することをお勧めします。要素の順序が重要でない場合は、リストではなくコレクションを使用します。これにより、コードに最大限の柔軟性がもたらされます。
一般的に、コード行では、インターフェースを気にすることは意味がありません。しかし、APIについて話をしている場合、本当に正当な理由があります。少人数クラス
class Counter {
static int sizeOf(List<?> items) {
return items.size();
}
}
この場合、インターフェースの使用が必要です。自分のカスタムを含めて可能な限り実装のサイズを数えたいので。 class MyList extends AbstractList<String>...
。