Javaのメソッドの返り値に、オブジェクトを使うべきかインターフェースを使うべきか

こんにちは。 エキサイト株式会社の三浦です。

Javaで配列を扱う時、すべての配列のインターフェースである List と、具体的に実装したオブジェクトである ArrayListLinkedList 等があります。 メソッドの返り値で配列を返したいときはこれらのどれでも使うことが出来ますが、実際にどれを使うべきなのでしょうか?

今回は、メソッドの返り値にインターフェースを使うべきか、それともオブジェクトを使うべきかについて説明していきます。

Javaの配列のインターフェースとオブジェクト

例えばPHPを使っている人にとっては、配列はそれ以上でもそれ以下でもありません。 ですが実はJavaには、「配列」と一口に言っても内部の保存方法によって種類が存在します。

例えば ArrayListLinkedList という形式がありますが、保存方法の違いにより、 ArrayList はランダムアクセスに強く、 LinkedList は要素の追加・削除に強いという特長があります。 そのため、その配列に対してどんな操作をしたいかによって、使う配列の形式を使い分けるのが良いでしょう。

そして、それらはすべて List というインターフェースを実装したものです。

さて、以上のことを踏まえると、配列を返すメソッドを考える時、ざっくり以下の2通りがあることがわかります。

// 返り値が、インターフェースである List
public List<String> getList() {
    return new ArrayList<String>();
}
// 返り値が、オブジェクトである ArrayList
public ArrayList<String> getList() {
    return new ArrayList<String>();
}

どちらでもコードとしては正しく動きますが、どちらを使うべきなのでしょうか? 実はこれは常に正しい方法が決まっているわけではなく、状況次第で変わってきます。

返り値の決定方法

まずは、それぞれのメリットを見ていきます。

インターフェースを使うメリット

  • 各オブジェクトそれぞれに固有のメソッドを使えなくなるので、配列オブジェクトを別の種類に変更しやすい
  • 空配列を使う場合のみに使用する emptyList 等が併用できる

オブジェクトを使うメリット

  • 各オブジェクトに固有のメソッドが使える
  • 使用するオブジェクトの種類を固定できる

以上のことから、まず各オブジェクトに固有のメソッド(例えば、 ArrayList にしか存在しないメソッド)を使いたい場合は、必ず返り値はオブジェクトにする必要があります。 また、パフォーマンス上どうしても使用するオブジェクトを固定する必要がある場合は、返り値をオブジェクトにしてもいいかもしれません。

それ以外の場合は、コードの柔軟性を考えると基本的にはインターフェースを使うのが良いかと思います。 また、仮にパフォーマンス上オブジェクトを固定する場合でも、メソッドの内部で負荷の高い処理が完結する場合や、よほどコードを固くする(ルールをがっちり決める)必要がない限りは返り値はインターフェースで十分なのではないでしょうか。 多くの場合は、コードの柔軟性確保のほうが全体としてメリットが上がる場合が多いです。

まとめ

どうしてもオブジェクトを使わなければならない状況以外では、コード柔軟性のためにインターフェースを使うほうが良いでしょう。

こうしたインターフェースとオブジェクトの仕組みは、配列だけでなくマップ(インターフェースの Map とオブジェクトの HashMap )等にもありますので、そういった状況でも同じ考え方が通用するはずです。