Вопрос по java, list, arrays – Нечетное обобщенное поведение List.toArray (T [])

23

Сегодня я наткнулся на что-то очень простое, но невероятное. Мне нужно было преобразовать список в массив. Список содержалString экземпляров. Прекрасный пример использованияList.toArray(T[]), так как я хотелString[] пример. Однако это не сработает без явного приведения результата кString[].

В качестве тестового сценария я использовал следующий код:

import java.util.Arrays;
import java.util.List;

public class MainClass {
    public static void main(String args[]) {
        List l = Arrays.asList("a", "b", "c");
        String stuff[] = l.toArray(new String[0]);
        System.err.println(Arrays.asList(stuff));
    }
}

который не компилируется. Это почти точная копия примера вJavadocТем не менее, компилятор говорит следующее:

MainClass.java:7: incompatible types
found   : java.lang.Object[]
required: java.lang.String[]
    String stuff[] = l.toArray(new String[0]);
                          ^

Если я добавлю приведение кString[] он будет компилироваться и работать отлично. Но это не то, чего я ожидаю, когда смотрю на сигнатуру метода toArray:

<T> T[] toArray(T[] a)

Это говорит мне, что я не должен был разыгрывать. Что здесь происходит?

Редактировать:

Любопытно, если я изменю объявление списка на:

List<?> l = Arrays.asList("a", "b", "c");

это тоже работает. Или жеList<Object>, Так что это не обязательно должно бытьList<String> как было предложено. Я начинаю думать, что используя сырьеList Тип также изменяет работу универсальных методов внутри этого класса.

Второе редактирование:

Я думаю, я понял это сейчас. То, что Том Хотин написал в комментарии ниже, кажется лучшим объяснением. Если вы используете обобщенный тип в необработанном виде, то вся информация об обобщениях из этого экземпляра будет стерта компилятором.

Ваш Ответ

5   ответов
0

List без объявленного типа по умолчанию будет "Список объектов" в то время какList<?> означает «Список неизвестных». В мире универсальных типов это факт, что «Список объектов» отличается от & quot; Список строк & quot; но компилятор не может сказать то же самое для & quot; списка неизвестных & quot ;. Если вы объявили это как неизвестное, то, насколько компилятор может сказать, что все в порядке.

Суть в том, чтобы объявить что-то подстановочным знаком? отличается от объявления его в качестве объекта. Подробнее о подстановочных знакахВот

3

или делать

List<?> l = Arrays.asList("a", "b", "c");  

still strange

Error: User Rate Limit Exceeded waxwing
Error: User Rate Limit Exceeded
1
List<String> l = Arrays.asList("a", "b", "c");

это заставит его скомпилироваться, вы используете обобщенные выражения, чтобы сказать: «Это список строк». поэтому метод toArray знает, какой тип массива возвращать.

29

Вы забыли указать параметр типа для своего списка:

List<String> l = Arrays.asList("a", "b", "c");

в этом случае вы можете написать безопасность:

String[] a = l.toArray(new String[0]);

без какого-либо состава.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded waxwing
Error: User Rate Limit Exceeded waxwing
Error: User Rate Limit Exceeded
0

Это потому, что ваш список содержит объекты, а не строки. Если бы вы объявили свой список какList<String>Компилятор был бы счастлив.

Похожие вопросы