Обновление: хотя я получил ответ, кажется, мое описание вопроса не очень понятно.Поэтому я сильно изменился, чтобы другие поняли мой вопрос.
Мое понимание причины, по которой массивы параметризованного типа не допускаются:
Integer[] b = {1,2,3};
Object[] a = b;
String[] c = {"123"};
a[0] = c; // Exception in thread "main" java.lang.ArrayStoreException
Integer i = b[0];
// Not really allowed.
List<String>[] lsa = new List<String>[10];
Object o = lsa;
Object[] oa = (Object[]) o;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
// Unsound, but passes run time store check
oa[1] = li;
// Run-time error: ClassCastException.
String s = lsa[1].get(0);
Эти две частикода имеет такую же структуру.
В части 1 Object[] a = b
заставляет a
и b
указывать на одну и ту же переменную b
.Так что a[0] = c
на самом деле меняется b
.Этот тип операции не вызовет никакого предупреждения при компиляции, но вызовет исключение ArrayStoreException.
Во второй части Object o = lsa; Object[] oa = (Object[]) o;
заставляет oa
и lsa
указывать на одну и ту же переменную lsa
, иoa[1] = li;
на самом деле меняется lsa
.
Поэтому я думаю, что именно по этой причине нельзя разрешать использование массивов параметризованного типа.
Если я правильно понимаю, случай, подобный T[] myArray
, также следует отклонить.Поскольку приведенный ниже код также имеет такую же структуру.
import java.util.*;
public class Test {
public static <T> void test(T[] t) {
Object[] a = t;
String[] c = {"123"};
a[0] = c;
T i = t[0];
}
public static void main(String[] args) {
Integer[] t = {1,2,3};
test(t);
}
}
Но в руководстве по Java
<T> T[] makeArray(T t) {
return new T[100]; // Error.
}
Причина, которую он дает,
Поскольку типПеременные не существуют во время выполнения, нет никакого способа определить, каким будет фактический тип массива.
Не та причина, которую я ожидаю.
Там также написано
Чтобы обойти эти ограничения, можно использовать литералы классов в качестве токенов типа времени выполнения
Так что я нашел пример в Generics gotchas .Код в разделе «Дорога не занята»:
public class ArrayList<V> implements List<V> {
private V[] backingArray;
private Class<V> elementType;
public ArrayList(Class<V> elementType) {
this.elementType = elementType;
backingArray = (V[]) Array.newInstance(elementType, DEFAULT_LENGTH);
}
}
Кажется, использование литералов класса уже решает проблему использования массива переменной типа (T []).Но проблема структуры, о которой я говорил в начале, все еще существует.Вспомните, я думаю, что структура всех трех частей кода не приводит к предупреждению компиляции, а к ошибке времени выполнения.
Итак, что не так с моим пониманием?
Большое вам спасибо за ваше время :)