lamrongol
@lamrongol (Lamron)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

`List list = new ArrayList()`と宣言するのはやめたほうがいいのではないか

ベストアンサー選択機能とかは無いようなので、 @mrbonjin さんの回答を転載:

ローカル変数に限れば優れた方法ではないです。
実装(クラス)ではなくインターフェースを用いた方が良い(変更に強くする)のはローカル変数ではなくメソッド引数や戻り値など他の機能との接点になるところです。


Stack Overflowでは具体的な質問以外は禁止とのことなのでQiitaで質問しますが、ArrayList list = new ArrayList()ではなくList list = new ArrayList()と書くのは本当に優れた方法なのでしょうか?

例えば英語版stackoverflowでは変化によく対応するためにList list = new ArrayList()という書き方がいいとされています。もしArrayListではなくLinkedListにした方がいい場合になったらnew ArrayList()の部分だけ書き変えればいい、と。

しかし、例えば以下のようなコードがあったとします。

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

/*

----------------------------------------------
長文のコード
----------------------------------------------

*/

Random rand = new Random();
for (int i = 0; i < list.size(); i++) {
    String str = list.get(rand.nextInt(list.size()));
    ...//processing
}

後任者が宣言文List<String> list = new ArrayList<>();だけ見て「なるほどこのlistはListであれば何でもいいんだな。じゃあちょっと挿入処理したい所があるからLinkedListに変えよう」とやったら以下の記事にあるように激遅コードになってしまいます。
軽い気持ちでLinkedListを使ったら休出する羽目になった話 - Qiita

Listに限らず、インターフェイスによる宣言は「そのインターフェイスが持つメソッドはどのような使われ方でも問題ない」場合だけ使うべきではないのではないでしょうか。例えばIterableインターフェイスなら「すべての要素を走査する」役割しかないので、どんな実装だろうと速度など何か問題が起きることは無いでしょう。

1

ArrayList型はList型を継承し内部で配列を持ちることで高速化(優れた)したものです。

new ArrayListで生成するならどちらでの良いのでは?(ArrayListは変数の型の合わせてくれます)

但し、後でデータ構造を複雑なもの(優れた)に変更する可能性があるなら、List型の方が良いとおもいます。

データを保存、取り出しにあった型を正しくチョイスすることが大切で、軽い気もちの責任はList型でも、ArrayList型でも、LinkedList型でもなく、選択したものが負うべきです。

0Like

ローカル変数に限れば優れた方法ではないです。
実装(クラス)ではなくインターフェースを用いた方が良い(変更に強くする)のはローカル変数ではなくメソッド引数や戻り値など他の機能との接点になるところです。

ローカル変数を宣言の時点でインターフェースにしてしまうと実装が持っている特有の機能が利用できなくなってしまいますので、そのせいで処理が冗長化したり複雑化してしまうこともありますのでわざわざインターフェースに変換(機能制限)する必要もないと思います。
例えば、Listの最後の要素を参照したいときにListのままならlist.get(list.size() - 1)のように参照する必要がありますがLinkedListならgetLast()で簡単に参照できたりします。

Java 10以降ならvarが使えるので変数の型をわざわざ考える必要もないので、このような心配も要らないでしょう。

3Like

明確にArrayListである必要性があるのであれば、ArrayListで宣言すればよいのではないでしょうか。汎用性の高い処理であれば、特定クラスへの依存を避けるためインターフェースとして扱った方が都合がよいでしょう。

0Like

質問ではなく意見交換であるなら、クローズ前についた回答への見解、意見くらいは書いたほうがいいと思いますよ。(何も意見交換されてない)
ただの質問であれば、最初から質問で投稿してください。

0Like

@radian-jp

質問ではなく意見交換であるなら、クローズ前についた回答への見解、意見くらいは書いたほうがいいと思いますよ。(何も意見交換されてない)

確かにその通りですね。以下で私の見解を書きます。

汎用性の高い処理であれば、特定クラスへの依存を避けるためインターフェースとして扱った方が都合がよいでしょう。

@mrbonjin 氏が書いているように、「メソッド引数や戻り値など他の機能との接点」なら汎用性が必要となるし、また、メソッド内でどんな処理を行なうかは自分で決められるためList型ならどんなクラスでも問題ないように書くことができるからインターフェイスで宣言した方がいいと思います。

@HalHarada

但し、後でデータ構造を複雑なもの(優れた)に変更する可能性があるなら、List型の方が良いとおもいます。

変更する可能性があるとしてもArrayListで宣言した方がいいのではないでしょうか。 @mrbonjin 氏が書いているように、Listで宣言してしまうとそのクラス特有の機能(メソッド)が使えなくなってしまいます。また、リーダブルコードであるためには、「このlist変数は(List型ならなんでもいい訳では無く)特定のクラス、あるいはそのクラスの利点を持ち他に欠点も無い上位互換のクラスにすべきだ」ということがわかるようにすべきだと思います。

1Like

new ArrayListならList型の派生であるArrayList型を用いるほうが無難です。

欠点も無い上位互換のクラスにすべきだ

変更する段階で、私は理想を追わず、気楽にList型を元或いはArrayList型を元に私独自クラスを作成すると思います。

0Like

Your answer might help someone💌