2

このエラーが発生します

java.lang.NullPointerException
    at java.util.ArrayList.<init>(Unknown Source)
    at de.mystuff.ExtendedArrayList.<init>(ExtendedArrayList.java:38)

ここで、ExtendedArrayList:38は

new ArrayList(new ArrayCollection<E>(data));

つまり、ArrayListコンストラクターは、自家製のコレクション実装ArrayCollectionを窒息させるように見えることがあります。

お客様に配布されたものとまったく同じバージョンでも、自分のコンピューターで再現することはできませんでした。

しかし、私たちが含めたJREを彼らが使用していることを100%確信しているわけではありません。だから、私はいくつかのArrayList.javaソースコードをグーグルで検索し、これを持っているopenJDK6b17を見つけました

public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    size = elementData.length;
    // c.toArray might (incorrectly) not return Object[] (see 6260652)
    if (elementData.getClass() != Object[].class)
        elementData = Arrays.copyOf(elementData, size, Object[].class);
}

データがない場合、ArrayCollection.toArray()はnullを返すため、これは理にかなっています。そして、このコンストラクターは、使用している1.5.0_09 Sun JDK / JRE実装に対して安全に見えました(そして例外なく機能しました)。
しかし、openJDKはUNIXの世界でしかリリースされていないようです。このコードもWindowsJREの一部ですか?もしそうなら、どのバージョンですか?

注意:クラスを修正する必要があることはわかっていますが、NullPointerExceptionの原因を確実に理解したいと思います。

4

4 に答える 4

7

長さがゼロの配列を返すのではなく、nullを返すことが正当であると考えるのはなぜですか?

のjavadocListではこれは許可されていません。したがって、原因は、他のすべてのJREが同じ仮定をしていることです。私のMacでSunの実装が公開しているソースは、確かにその仮定をしています。

于 2010-01-06T12:16:27.497 に答える
1

J2SE 5.0 APIドキュメントによると:

ArrayList public ArrayList(Collection c)指定されたコレクションの要素を含むリストを、コレクションのイテレーターによって返される順序で作成します。ArrayListインスタンスの初期容量は、指定されたコレクションのサイズの110%です。

パラメータ:c-このリストに要素が配置されるコレクション。

スロー:
NullPointerException-指定されたコレクションがnullの場合。

それで

new ArrayList(new ArrayCollection<E>(data));

がnullのNullPointerException場合にスローします。new ArrayCollection<E>(data)

編集:

140     /**
141      * Constructs a list containing the elements of the specified
142      * collection, in the order they are returned by the collection's
143      * iterator.
144      *
145      * @param c the collection whose elements are to be placed into this list
146      * @throws NullPointerException if the specified collection is null
147      */
148     public ArrayList(Collection<? extends E> c) {
149     elementData = c.toArray();
150     size = elementData.length;
151     // c.toArray might (incorrectly) not return Object[] (see 6260652)
152     if (elementData.getClass() != Object[].class)
153         elementData = Arrays.copyOf(elementData, size, Object[].class);
154     }

OpenJDKのArrayListコンストラクターにはこれらの行があります。このコンストラクターのドキュメントによると:146 * @throws NullPointerException(指定されたコレクションがnullの場合)

コレクションがnullの場合にのみ例外をスローする必要があります。

ここにこれらの行があります:

149     elementData = c.toArray();
150     size = elementData.length;

Collection.toArray().lengthメソッドが呼び出されます。

実装Collection.toArray()ではnullであるため、NullPointerExceptionがスローされます。

J2SECollection.toArrayのドキュメントによると

toArray Object [] toArray()このコレクションのすべての要素を含む配列を返します。コレクションがイテレータによって要素が返される順序を保証する場合、このメソッドは同じ順序で要素を返す必要があります。

返される配列は、このコレクションによって参照が維持されないという点で「安全」です。(つまり、このコレクションが配列によってサポートされている場合でも、このメソッドは新しい配列を割り当てる必要があります)。したがって、呼び出し元は返された配列を自由に変更できます。

このメソッドは、配列ベースのAPIとコレクションベースのAPIの間のブリッジとして機能します。

戻り値:このコレクションのすべての要素を含む配列

したがって、nullを返さないようにする必要があります。空の配列を返す必要があります。したがって、.lengthは0を返し、問題はありません。

于 2010-01-06T12:32:39.763 に答える
1

List#toArrayメソッドがnullを返すことはありません。ArrayCollectionの実装は、toArrayメソッドをオーバーライドしている可能性があり、新しい空の配列ではなく、空のコレクションに対してnullを返している可能性があります。

もちろん、JREが異なれば動作も異なる可能性があります。配列の代わりにnullを許容するものもあれば、許容しないものもあります。

Javaデコンパイラーを起動して、このArrayListコンストラクターの実際の実装を確認します。

于 2010-01-06T12:59:19.987 に答える
1

使用しているJREのバージョン/ベンダーを正確に指定したとは思いませんが、Sun JDK 1.6.0_17の問題のコンストラクターのソースは次のとおりです(まだ知らない場合は、java名前空間内のほとんどのクラスのソース) JDKに同梱):

public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    size = elementData.length;
    // c.toArray might (incorrectly) not return Object[] (see 6260652)
    if (elementData.getClass() != Object[].class)
         elementData = Arrays.copyOf(elementData, size, Object[].class);
}

(コメントは著者のものであり、私のものではありません)

これは、このコンストラクターでのNPEの潜在的な原因をかなり明確に示しているはずです。ifcがnullであるか、(あなたの場合)ifc.toArray()がnullを返します。

于 2010-01-06T13:05:50.350 に答える