次の条件がJDK 8ではtrue
を返すのに、JDK 9ではfalse
を返すのはなぜですか?
String[].class == Arrays.asList("a", "b").toArray().getClass()
List
によって返されるasList
タイプは Arrays$ArrayList
です。そのクラスのJDK 8のtoArray
メソッドは次のとおりです。
@Override
public Object[] toArray() {
return a.clone();
}
ただし、JDK 9以降では次のようになります。
@Override
public Object[] toArray() {
return Arrays.copyOf(a, a.length, Object[].class);
}
どちらの場合もString[]
がasList
に渡されますが、JDK 8の場合は複製され、その配列型(String[]
)が保持され、JDK 9+ではコピーされますArrays.copyOf
の明示的な新しい配列タイプでObject[]
を使用します。
この違いは、JDK 8 Arrays.asList("a", "b").toArray().getClass()
ではString[]
を返し、JDK 9+ではObject[]
を返すため、JDK 9+では式はfalse
に評価されます。
この変更の理由は、 JDK-6260652 の動機によるものです。
コレクションのドキュメントでは、
collection.toArray()
「機能的に同一」である
collection.toArray(new Object[0]);
ただし、
Arrays.asList
の実装はこれに従いません。サブタイプの配列(たとえばString[]
)で作成された場合、そのtoArray()
は同じ型の配列を返します(なぜならObject[]
の代わりにclone()
)を使用します。後でその配列に非文字列(またはその他)を保存しようとすると、
ArrayStoreException
がスローされます。
この変更は、以前の動作を修正するために行われました。
これがあなたにとって問題であれば、関連する リリースノート は回避策としてこれを提供します:
この問題が発生した場合、1引数形式
toArray(T[])
を使用するようにコードを書き直し、目的の配列タイプのインスタンスを提供します。これにより、キャストも不要になります。String[] array = list.toArray(new String[0]);
これはJDK 8のバグであり、それが修正される前のことです。
List<T>.toArray()
は常にObject[]
を返すと宣言されていました( JavaDoc を参照)-特別な場合にString[]
を返すことは間違いでした。