Problem initialize List <Object []> Использование Arrays.asList
Когда я инициализирую List, я могу это сделать:
List<Object[]> foo = new ArrayList<>();
foo.add(new Object[]{816, "foo", 2.6});
Но когда я хочу упростить его, используя Arrays.asList
:
List<Object[]> bar = Arrays.asList(new Object[]{"bar", 286});
Он не может скомпилироваться с ошибкой:
incompatible types: inference variable T has incompatible bounds
equality constraints: java.lang.Object[]
lower bounds: java.lang.Object
Почему он не может правильно сделать вывод типа и как это исправить?
Ответы
Ответ 1
Помните, что ...
- это просто синтаксический сахар для параметра массива. Вы можете вызвать метод с переменным параметром foo(Object...)
либо с помощью
foo("hello", 1);
или
foo(new Object[]{"hello", 1});
так как компилятор все равно конструирует вторую форму.
Поскольку тип приемника не учитывается, когда компилятор вводит типы, он смотрит на Arrays.asList(new Object[]{"bar", 286})
и считает, что вы хотите создать список Object
, а не один список из Object[]
.
Самый простой способ с вашим существующим синтаксисом - просто добавить явный тип типа:
List<Object[]> bar = Arrays.<Object[]>asList(new Object[]{"bar", 286});
Добавление <Object[]>
сообщает компилятору, что такое T.
Ответ 2
Когда вы передаете массив ссылочных типов в Arrays.asList
, вы получите List
этого ссылочного типа.
Поэтому Arrays.asList(new Object[]{"bar", 286})
возвращает a List<Object>
, а не a List<Object[]>
.
Ответ 3
Если ваш список содержит только один элемент, Collections.singletonList(new Object[] {...})
- лучший выбор, поскольку он избегает varargs и делает поведение более очевидным на сайте вызова.
Ответ 4
Проблема заключается в том, что Arrays.asList
- это метод varargs, который технически получает массив, содержащий аргументы, и из-за совместимости с кодом pre-generics все еще принимает массив вместо списка аргументов. При передаче одного массива вызов неоднозначен и будет обрабатываться как вызов метода pre-varargs.
Проблема исчезает, когда у вас есть несколько аргументов:
List<Object[]> bar = Arrays.asList(new Object[]{"bar", 286}, new Object[]{"baz", 123});
Если у вас есть только один аргумент, вы можете помочь компилятору, вставив явный тип элемента списка:
List<Object[]> bar = Arrays.<Object[]>asList(new Object[]{"bar", 286});
В качестве альтернативы вы можете использовать
List<Object[]> bar = Collections.singletonList(new Object[]{"bar", 286});
чтобы создать неизменный список размера один. Обратите внимание, что это отличается от Arrays.asList
, поскольку последний возвращает список фиксированного размера, но все же изменяемый с помощью set
.
Ответ 5
Arrays#asList
подпись:
public static <T> List<T> asList(T... a)
Тип возврата List<T>
. Теперь вы должны спросить себя, что такое T
?
T
Object
, поэтому возвращаемый тип будет List<Object>
, а не List<Object[]>
.
Ответ 6
Ваш звонок:
Arrays.asList(new Object[]{"bar", 286});
создает список из Object[]
. Таким образом, данные преобразуются в новый List<Object>
.
Итак Arrays.asList(new Object[]{"bar", 286}).get(0);
вернет "бар".
В этом вызове:
List<Object[]> foo = new ArrayList<>();
foo.add(new Object[]{816, "foo", 2.6});
вы создаете List<Object[]>
(двумерный) и добавляете по нему один элемент: foo.add(..);
.
Поэтому вы добавляете один элемент, состоящий из Object[]
.
если вы сейчас звоните foo.get(0);
, вы получите Object[]
, состоящий из:
816, "foo", 2.6
Я думаю, вы хотели:
Object[] oa = new Object[]{""};
Object[] ob = new Object[]{""};
List<Object[]> list = Arrays.asList(oa, ob);
Если у вас есть вопросы, не стесняйтесь спрашивать меня:)
Ответ 7
Когда вы используете List<Object[]> bar = Arrays.asList(new Object[]{"bar", 286});
, на самом деле у вас есть двумерный массив, и вы можете решить эту проблему, выполнив List<Object[]> bar = Arrays.asList(new Object[][]{new Object[]{"bar","asd",123}});