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}});