

プログラミング入門などではよく`ArrayList list = new ArrayList()`ではなく`List list = new
ArrayList()`と書きましょうという記述がありますが、本当にこれは優れた書き方なのでしょうか？  
例えば[英語のstackoverflow](https://stackoverflow.com/questions/18329311/reason-for-
list-list-new-arraylist)では変化によく対応するために`List list = new
ArrayList()`という書き方がいいとされています。もしArrayListではなくLinkedListにした方がいい場合になったら`new
ArrayList()`の部分だけ書き変えればいい、と。

しかし本当にそうでしょうか。[軽い気持ちでLinkedListを使ったら休出する羽目になった話 -
Qiita](https://qiita.com/neko_machi/items/d620c4a8958e74df3550)のように、以下のコードのようなランダムアクセスが多発するコードを書いていた場合、

[code]

    for (int i = 0; i*2 < data.size(); i++) {
        MyClass record = data.get(i*2);
    }
    
[/code]

`List list = new
ArrayList()`という記述を見て後任者が「なるほどこのコードではListであれば何でもいいんだな。じゃあちょっと挿入処理したい所があるからLinkedListに変えよう」となったら記事にあるように激遅コードになってしまいます。

Listに限らず、インターフェイスによる宣言は「そのインターフェイスで実装されるメソッドはすべて同様の動作をする」ことが保証されない限り使うべきではないのではないでしょうか。

追記：英語版でも質問してみました <https://stackoverflow.com/questions/64868813/is-list-list-
new-arraylist-really-desirable-from-arraylist-list-new-arr>


CC BY-SA 4.0
2020-11-16T23:30:19.163
71993
2020-11-17T10:47:21.093
2020-11-17T04:12:46.083
816
816
question
java
List list = new ArrayList()と宣言するのはやめたほうがいいのではないか


java でこの問題がどう取り扱われているかというと、[RandomAccess
interface](https://docs.oracle.com/javase/jp/7/api/java/util/RandomAccess.html)が提供されていて、少なくとも
`instanceof` で与えられた List を実装しているオブジェクトが random access 可能かを判定できるようになっている様子です。

ポイントは、具体的な実装クラスだと変更可能性に欠けるが、`List`
だとゆるすぎるのが問題だと思っており、もしランダムアクセス機能がクリティカルな場合には、その箇所で runtime チェックを行って、
RandomAccess の instance じゃなかったら例外を発生させる、みたいな実装がありえるかな、と思いました。

Java なので、何かしらのテストは実装していると思われるので、そこで例えば `LinkedList` を与えた場合には例外が発生して test が
fail するようにすれば、他の実装者はそこで気付けるようになるのではないかな、と思います。


CC BY-SA 4.0
2020-11-17T03:10:36.883
71994
2020-11-17T03:10:36.883
754
71993
answer


私も大体同じような考えを持っており「Javaが標準で持っているクラスのインスタンスは、インタフェース名で受けない」方が良いと考えています。  
コレクションに関して言えば、インタフェース名で受けるのはメソッドの引数くらいかなと思います。


CC BY-SA 4.0
2020-11-17T04:00:10.577
71995
2020-11-17T04:00:10.577
42750
71993
answer


設計としてArrayListの機能を要求されるのであればArrayListにするべきだと思いますし、汎用的なメソッド的なものを想定しているのであればListにすればよいのではないのでしょうか。  
一概にこうすべき、と断じれるものではないと思います。  
設計には前提が必要であり、特に前提を定めないのであれば、可能な限り抽象化しておくのが理想ではないかなと個人的に思います。


CC BY-SA 4.0
2020-11-17T04:10:35.690
71996
2020-11-17T04:56:04.970
2020-11-17T04:56:04.970
41943
41943
71993
answer


`List`型(インタフェース)より具象型で表す方が妥当な状況もあるかとは思いますが、質問文リンク先[Qiitaの事例](https://qiita.com/neko_machi/items/d620c4a8958e74df3550)、及び質問文中の事例とも、特にそういった状況には当てはまらない(つまり`List`を用いるのが妥当)かと思います。

* * *

インタフェースに対しては **利用者** と **提供者**
(実装者)という2つの立場があり、Qiitaの記事は利用者の、質問文のものは提供者の立場の事例です(※質問文の事例はどちらとも取れるので誤解しているかもしれません)。

そして具象型でなく`List`型として提供するのは、 **利用者** が実装を意識せずに済むのが利点であり、 **提供者**
に対する利点ではないです。つまり、質問文の事例では

> 「なるほどこのコードではListであれば何でもいいんだな。じゃあちょっと挿入処理したい所があるからLinkedListに変えよう」

という考え方が誤りであり、提供者は`List`かどうかに関わらず想定される利用方法に対して適切な実装を提供する必要があります。

他方、Qiitaの事例は、`List`の利用方法の誤りだと言えるかと思います。

<https://docs.oracle.com/javase/jp/11/docs/api/java.base/java/util/List.html>

> 一部の実装(LinkedListクラスなど)では、これらのオペレーションの実行にはインデックス値に比例した時間がかかる場合があります。
> このため、呼出し側がこうした実装について知らない場合は、リストにインデックスを付けるよりも、リスト内の要素を反復してください。

* * *

> インターフェイスによる宣言は「そのインターフェイスで実装されるメソッドはすべて同様の動作をする」ことが保証されない限り使うべきではない

(この点について留意すべき者は利用者でなく提供者かと考えますが、この点はひとまず置いておいて)  
今回の事例で言うと、`List`はインデクスによるアクセスの計算量について何か規定/保証しているわけではありません。  
むしろ、実装によって計算量が異なることを示唆しており、実際にそうなっている、ということです。


CC BY-SA 4.0
2020-11-17T10:47:21.093
72008
2020-11-17T10:47:21.093
2808
71993
answer