33

Best Practices: Always return a ____, never a ____の精神で、JDK1.4.2 から JDK5 などへの今後の移行で同様の質問に直面します。(はい、知ってます。JDK1.4.2 は EOL です! ;-) )。

コレクション (単純なプロパティ コレクションではない) を返す関数の場合、(JDK1.4.2 では) 一般的な List ではなく Array を返すことを常に好みます。

  • 返される型を強制します(オブジェクトのリストの代わりに、「コンパイル」レベルのように、静的でMyObject[]よりタイプセーフです)
  • 返されたコレクションに「読み取り専用」文字を提案します (これは c# の「読み取り専用」キーワードほど厳密ではありませんが、コレクションに要素を追加するのはより複雑です)。これは、配列内の参照を変更できるため、「不変」であると言っているのと同じではありません...

もちろん、私は常にこの返された配列を作成します(「内部」配列は公開しません)。

現在、JDK5以降では、必要に応じて使用できますList<MyObject>

MyObject[]List の代わりに返すことを選択する、またはCollection<MyObject>java5 でコーディングする場合の正当な理由は何ですか?

ボーナスをCollection<MyObject>使用する場合、次のことは可能ですか。

  • 返されたコレクションに読み取り専用属性を適用しますか? (いいえadd()またはremove()可能)
  • 返されたコレクションに不変の側面を強制しますか? (そのコレクションの参照も変更できません)

PS: JavaGenericFAQにはそれがまったくありませんでした。

4

4 に答える 4

37

配列よりもコレクション(またはリスト、または必要に応じて設定)を優先します。ジェネリックスを使用すると、Java 5より前のバージョンに欠けていた型チェックを取得できます。また、インターフェースのみを公開することで、後で実装を自由に変更できます(たとえば、LinkedListのArrayListを切り替えます)。

配列とジェネリックはあまりうまく混ざりません。したがって、ジェネリックスを利用したい場合は、通常、配列を避ける必要があります。
つまり、一般的に配列を作成することはできません。たとえば、Tがジェネリック型の場合、「newT[0]」はコンパイルされません。「(T [])new Object [0]」のようなことをする必要があります。これは、チェックされていないキャスト警告を生成します。同じ理由で、警告なしにvarargsでジェネリック型を使用することはできません。

Collections.unmodizableCollection (および同様のメソッド)を使用すると、読み取り専用の制約が発生します(これは、配列では実現できません。配列のクローンを返す必要があります)。

メンバーの不変性を強制することはできませんが、配列を使用して強制することもできません。

于 2008-10-22T12:51:50.150 に答える
11

実際、配列には、コレクション/リストに比べて1つの利点があります。Javaが型消去を介してジェネリックスを実装する方法により、コレクションを引数として受け取る2つのメソッドを使用することはできませんが、コレクションのジェネリック型のみが異なります。

元:

public void doSomething(Collection<String> strs) { ... }
public void doSomething(Collection<Integer> ints) { ... }

javacコンパイラは型消去を使用し、型情報をJVMに渡すことができないため、上記の2つのメソッドはコンパイルされません。JVMは、コレクションを引数として取る2つのメソッドのみを認識します。

上記の場合、最善の回避策は、メソッドが配列を引数として取り、引数を渡すときにCollection / ListのtoArray()メソッドを使用するようにすることです。上記のメソッド内でCollection/Listを引き続き使用する場合は、java.util.Arrays.asList()メソッドを使用してリストを元に戻します。

元:

public void doSomething(String[] strs) {
        List<String> strList = Arrays.asList(strs);
        ...
}

public void doSomething(Integer[] ints) {
        List<Integer> intList = Arrays.asList(ints);
        ...
}

public static void main(String[] args) {
        List<String> strs = new ArrayList<String>();
        List<Integer> ints = new ArrayList<Integer>();
        obj.doSomething(strs.toArray());
        obj.doSomething(ints.toArray());
}
于 2008-11-10T07:52:01.907 に答える
4

クラス内の変更不可能な*メソッドをチェックして、Collections返されたコレクションを読み取り専用/不変にします。これにより、元のコレクションがリストにラップされ、リスト自体の変更にアクセスできなくなります(ただし、要素自体は不変ではありません)。

たとえば、 unmodizableList

私にとっては、返されたリストがどのように使用されるかによって異なります。他にどのようなメソッドに渡され、どのように使用されますか?一般に、配列よりもジェネリックコレクションの方が好きですが、ケースバイケースで変更します。

重要なことをしている場合は、アレイのパフォーマンスもおそらく速くなります。

于 2008-10-22T12:53:45.093 に答える
3

クラスにプロキシを使用し、そのようなもの(プロキシとリフレクション)の使用は一部の人々の心のパフォーマンスに影響を与えるため禁止されているため、私の答えは反対票を投じられました(多くの人はリフレクションを使用することさえありませんが、リフレクションを使用する休止状態と春を使用します、クラス プロキシおよび xml)。

cglib.sourceforge.net プロジェクトのエンハンサーで、クラスのプロキシを作成できます (JDK はインターフェイスのプロキシのみをサポートします)。プロキシを使用すると、オブジェクトのメソッドを制御できますが、リフレクションを使用してフィールドにアクセスすることはできません。質問があれば聞いてください。

于 2008-10-23T13:41:26.323 に答える