Javaクラスのインターフェースを優先する必要があるのはなぜですか?

StackOverflow https://stackoverflow.com/questions/147468

  •  02-07-2019
  •  | 
  •  

質問

PMD は、次の違反を報告します。

ArrayList<Object> list = new ArrayList<Object>();

違反は<!> quot; 'ArrayList'などの実装タイプの使用を避けます。代わりにインターフェイスを使用してください<!> quot;。

次の行は違反を修正します:

List<Object> list = new ArrayList<Object>();

なぜListの代わりにArrayListを使用する必要があるのですか?

役に立ちましたか?

解決

具体的な型でインターフェイスを使用することは、適切なカプセル化とコードの疎結合の鍵となります。

独自のAPIを作成するときは、このプラクティスに従うことをお勧めします。そうした場合、後でコードにユニットテストを追加する(モッキングテクニックを使用する)ことが簡単になり、将来必要に応じて基礎となる実装を変更できることがわかります。

良い記事は件名。

お役に立てばと思います!

他のヒント

これは、リストの実装からコードを切り離すために推奨されます。インターフェイスを使用すると、Listで定義されたメソッドのみを使用する限り、残りのコードを変更せずに、実装(この場合はArrayList)を別のリスト実装に簡単に変更できます。

一般に、インターフェイスを実装から切り離すことは良いことであり、コードの保守が容易になることに同意します。

ただし、考慮すべき例外があります。インターフェイスを介してオブジェクトにアクセスすると、コードの速度を低下させる間接的なレイヤーが追加されます。

興味を引くために、100万のArrayListに100億のシーケンシャルアクセスを生成する実験を実行しました。私の2.4Ghz MacBookでは、Listインターフェイスを介してArrayListにアクセスするのに平均2.10秒かかりましたが、ArrayList型で宣言すると平均1.67秒かかりました。

大きなリスト、内部ループの奥深く、または頻繁に呼び出される関数を使用している場合、これは考慮すべき事項です。

ArrayListおよびLinkedListは、リストの2つの実装であり、アイテムの順序付けられたコレクションです。論理的には、ArrayListを使用するかLinkedListを使用するかは問題ではないため、型をそのように制限するべきではありません。

これは、異なるコレクションであるコレクションとリストとは対照的です(リストはソートを意味し、コレクションはソートを意味しません)。

  

なぜArrayListの代わりに後者のListを使用する必要があるのですか

それは良い習慣です:実装ではなくインターフェースするプログラム

ArrayListListに置き換えることにより、ビジネスユースケースに応じて、以下のように<=>実装を将来変更できます。

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).*/

または

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.*/

または

List<Object> list = new  Stack<Object>(); 

/* The Stack class represents a last-in-first-out (LIFO) stack of objects.*/

または

その他の<=>特定の実装。

<=>インターフェイスはコントラクトを定義し、<=>の特定の実装を変更できます。このように、インターフェースと実装は疎結合です。

関連するSEの質問:

<!> quot; programの意味インターフェースへ<!> quot ;?

ローカル変数であっても、具象クラスでインターフェースを使用すると役立ちます。インターフェースの外部にあるメソッドを呼び出すことになり、必要に応じてリストの実装を変更することは困難です。 また、宣言で最も具体性の低いクラスまたはインターフェイスを使用することをお勧めします。要素の順序が重要でない場合は、リストの代わりにコレクションを使用します。これにより、コードに最大限の柔軟性が与えられます。

クラス/インターフェースのプロパティは、実装に関係なく、使用する動作のコントラクトをクラスに与えるため、インターフェースを介して公開する必要があります。

ただし...

ローカル変数宣言では、これを行うのはほとんど意味がありません:

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>...

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top