608
(1) List<?> myList = new ArrayList<?>();

(2) ArrayList<?> myList = new ArrayList<?>();

(1)でListインターフェースの実装がスワップできることは理解しています。(1)は必要に応じてアプリケーションで使用されることが多いようです (私自身は常にこれを使用しています)。

誰かが(2)を使用しているかどうか疑問に思っていますか?

また、実際に (1) を (2) よりも使用する必要がある状況 (つまり、(2) では不十分な場合。インターフェースベスト プラクティスなどへのコーディングは別として) の頻度 (例を教えてください) はどれくらいですか?

4

15 に答える 15

486

たとえば、コードベースの残りの部分に影響を与えずに に変換できるため、ほぼ常にListが優先されます。ArrayListListLinkedList

ArrayListの代わりに1 つを使用すると、再構築が必要な特定のメソッドがコードベースで使用されているため、実装を1 つListに変更することは困難です。ArrayListLinkedListArrayList

ここListで実装について読むことができます。

から始めることもできますがArrayList、すぐに別の実装の方が適切な選択であることがわかります。

于 2010-02-17T07:46:11.893 に答える
124

誰かが(2)を使用しているかどうか疑問に思っていますか?

はい。しかし、正当な理由(IMO)でめったにありません。

ArrayListそして、人々は、使うべきときに使ったためにやけどを負いますList:

  • Collections.singletonList(...)or Arrays.asList(...)do not のようなユーティリティ メソッドはArrayList.

  • APIのメソッドはList、同じ型のリストを返すことを保証しません。

誰かがやけどを負った例として、https://stackoverflow.com/a/1481123/139985では、ポスターは「スライス」に問題がArrayList.sublist(...)ありArrayListましArrayListた。彼のリスト変数のすべて。彼は、サブリストを新しい にコピーすることで問題を「解決」しましたArrayList

動作がどのように動作するかを知る必要があるという議論は、マーカー インターフェイスListを使用することで大部分解決されます。RandomAccessはい、少し不格好ですが、代替手段はさらに悪いです。

また、どのくらいの頻度で (1) を (2) よりも実際に使用する必要がありますか (つまり、(2) では不十分な場合です。「インターフェースへのコーディング」やベスト プラクティスなどは別として)。

質問の「どのくらいの頻度」の部分は、客観的に答えられません。

(そして、私は例を得ることができますか)

場合によっては、 API にないArrayListメソッドをAPI で使用する必要がある場合があります。たとえば、、または. (そして最後のものは、メソッドが であることを宣言する ArrayList のサブタイプを作成した場合にのみ発生します。)ListensureCapacity(int)trimToSize()removeRange(int, int)public

それが、IMO インターフェイスではなくクラスにコーディングする唯一の正当な理由です。

(理論的には、パフォーマンスがわずかに向上する可能性があります...特定の状況下...一部のプラットフォームでは...しかし、最後の0.05%が本当に必要でない限り、これを行う価値はありません。これは正当な理由、IMO.)


ランダムアクセスが効率的かどうかを知らなければ、効率的なコードを書くことはできません。

それは有効な点です。ただし、Java はそれを処理するためのより良い方法を提供します。例えば

public <T extends List & RandomAccess> void test(T list) {
    // do stuff
}

実装されていないリストでそれを呼び出すとRandomAccess、コンパイル エラーが発生します。

動的にテストすることもできます ... を使用してinstanceof... 静的な型付けが面倒な場合。また、リストがランダム アクセスをサポートしているかどうかに応じて、異なるアルゴリズムを (動的に) 使用するようにコードを記述することもできます。

ArrayListを実装する唯一のリスト クラスではないことに注意してくださいRandomAccess。その他にはCopyOnWriteList、 、Stackおよびが含まれVectorます。

私は人々がSerializableListそれを実装していないため)について同じ議論をするのを見てきました...しかし、上記のアプローチはこの問題も解決します。(ランタイム型を使用して解決できるArrayList範囲で。任意の要素がシリアライズ可能でない場合、An はシリアライズに失敗します。)


最後に、「スタイルがいいから」とは言いません。その「理由」は、回りくどい議論 (「なぜそれが「スタイルが良い」のか?」) であると同時に、明言されていない (そしておそらく存在しない!) 上位の権威 (「スタイルが良い」とが言ったのか?) への訴えでもあります。 .

(インターフェイスにプログラムするのは良いスタイルだと思いますが、それを理由として挙げるつもりはありません。本当の理由を理解し、(IMO) 正しい結論に達する方が良いでしょう。文脈によっては、正しい結論が常に同じであるとは限りません。)

于 2010-02-17T07:50:13.810 に答える
46

たとえばLinkedList、アプリケーションにとっては が最適な選択であると判断したとしても、後でArrayListパフォーマンス上の理由から の方が適していると判断する場合があります。

使用する:

List list = new ArrayList(100); // will be better also to set the initial capacity of a collection 

それ以外の:

ArrayList list = new ArrayList();

参考のため:

ここに画像の説明を入力

(主にコレクション図に投稿)

于 2014-09-09T15:12:05.337 に答える
14

コードがリストの「所有者」である場合、(2) を使用します。これは、たとえば、ローカルのみの変数に当てはまります。Listの代わりに抽象型を使用する理由はありませんArrayList。所有権を示す別の例:

public class Test {

    // This object is the owner of strings, so use the concrete type.
    private final ArrayList<String> strings = new ArrayList<>();

    // This object uses the argument but doesn't own it, so use abstract type.
    public void addStrings(List<String> add) {
        strings.addAll(add);
    }

    // Here we return the list but we do not give ownership away, so use abstract type. This also allows to create optionally an unmodifiable list.
    public List<String> getStrings() {
        return Collections.unmodifiableList(strings);
    }

    // Here we create a new list and give ownership to the caller. Use concrete type.
    public ArrayList<String> getStringsCopy() {
        return new ArrayList<>(strings);
    }
}
于 2013-04-21T12:20:37.030 に答える
9
(3) Collection myCollection = new ArrayList<?>();

私はこれを通常使用しています。List メソッドが必要な場合にのみ、 List を使用します。ArrayList と同じです。いつでもより「狭い」インターフェイスに切り替えることができますが、より「広い」インターフェイスに切り替えることはできません。

于 2010-02-17T07:51:38.717 に答える
9

(2)を使っている人は、リスコフの置換原理依存性反転原理を知らないと思います。または、実際に使用する必要がありますArrayList

于 2010-02-17T07:55:27.803 に答える
8

次の2つのうち:

(1) List<?> myList = new ArrayList<?>();
(2) ArrayList<?> myList = new ArrayList<?>();

一般的には最初が好まれます。インターフェイスからのみメソッドを使用するため、将来、たとえばList他の実装を自由に使用できます。したがって、特定の実装から切り離されます。ここで、言及する価値のある 2 つのポイントがあります。ListLinkedList

  1. 常にインターフェイスするようにプログラムする必要があります。詳細はこちら
  2. ほとんどの場合、 ArrayListoverを使用することになりLinkedListます。詳細はこちら

誰かが使っているかどうか疑問に思っています (2)

はい、時々(めったに読まない)。ArrayListインターフェイスの一部ではなく実装の一部であるメソッドが必要な場合List。たとえばensureCapacity

また、どのくらいの頻度で (例を教えてください)、実際に (1) を (2) よりも使用する必要がありますか?

ほとんどの場合、オプション (1) を好みます。これは OOP の古典的な設計パターンであり、常にコードを特定の実装およびプログラムからインターフェイスに分離しようとします。

于 2015-07-03T08:40:04.940 に答える
4

リストはインターフェースです。メソッドはありません。List 参照でメソッドを呼び出すと、実際にはどちらの場合も ArrayList のメソッドが呼び出されます。

また、将来的には、またはList インターフェイスを実装する他のタイプにList obj = new ArrayList<>変更 できます。List obj = new LinkList<>

于 2015-10-27T11:50:44.923 に答える
2

(2) の方が優れていると私が認識している唯一のケースは、GWT を使用する場合です。これは、アプリケーションのフットプリントを削減するためです (私の考えではありませんが、Google Web ツールキット チームはそう言っています)。しかし、通常の Java を JVM 内で実行する場合 (1) は、おそらく常に優れています。

于 2010-02-17T07:54:29.607 に答える
1

1 が好ましいと言えます。

  • ArrayList のオプションの動作* の実装に依存している場合、明示的に ArrayList を使用する方が明確です
  • おそらくオプションの動作またはパフォーマンス特性のために、ArrayList を必要とするメソッド呼び出しで ArrayList を使用します。

私の推測では、ケースの 99% で List を使用できますが、これが推奨されます。

  • たとえばremoveAll、またはadd(null)
于 2010-02-17T07:47:58.603 に答える