Я сделал обзор кода для моего коллеги два дня назад. Я чувствовал, что у меня не было хорошего понимания дженериков Java, поэтому я взял книгу «Эффективная Java» 1, а затем посмотрел на соответствующие главы. В пункте 24: Устранение разделения неконтролируемых предупреждений автор использует публичный метод <t> t [] toarray (t [] a) в классе ArrayList в качестве примера, чтобы проиллюстрировать, как использовать аннотацию @suppresswarnings для переменных.
ArrayList - это общий класс, который объявляется так:
Javapublic Class ArrayList <e> расширяет AbstractList <e> List <e>, Randomaccess, Clonable, Java.io.serializable
Метод Toarray (T [] a) этого класса является общим методом, который объявляется и реализуется таким образом:
@Suppresswarnings ("unchecked") public <t> t [] toarray (t [] a) {if (a.length <size) // Сделать новый массив типа времени выполнения A, но мое содержимое: return (t []) arrays.copyof (elementdata, size, a.getclass (); System.ArrayCopy (elementDAta, 0, a., id, if -lepende); размер) a [size] = null; вернуть a;} Этот метод фактически объявлен в интерфейсе сбора. Поскольку мы часто используем его через ArrayList, мы будем использовать ArrayList в качестве примера здесь.
1 Почему он объявляется другим типом?
Мой вопрос: почему этот метод использует тип T вместо типа E ArrayList? То есть почему этот метод не объявляется так:
Javapublic e [] toarray (e [] a);
Если типы одинаковы, ошибка типа параметра можно найти во время компиляции. Если типы разные, легко генерировать ошибки времени выполнения. Например, следующий код:
// Создать arraylist <string> strlist = new ArrayList <string> (); strist.add ("abc"); strist.add ("xyz"); // Конвертировать текущий strist в чисел массив. Обратите внимание, что в следующем операторе нет ошибок компиляции. Номер [] numarray = strlist.toarray (новый номер [0]); Запустите приведенный выше код, а строка 6 бросит исключение java.lang.arraystoreException.
Если метод Toarray использует тип E, оператор 2 будет генерировать ошибку компиляции. Ошибки компиляции более дружелюбны, чем ошибки времени выполнения. Кроме того, основная цель генерики - устранить ошибки преобразования типа (ClassCastException) во время компиляции. Этот метод наоборот. Это большая ошибка? Я столкнулся с явной ошибкой, но я все еще не могу в это поверить.
После проверки Интернета этот вопрос обсуждался много раз 2, 3, 4.
2 может повысить гибкость
Это объявление является более гибким и может преобразовать элементы в текущем списке в массив более общих типов. Например, текущий тип списка является целым числом, и мы можем преобразовать его элементы в числовой массив.
Список <Integer> intlist = new ArrayList <Integer> (); intlist.add (1); intlist.add (2); number [] numarray = intlist.toarray (новый номер [0]);
Если этот метод объявлен как тип E, приведенный выше код будет иметь ошибку компиляции. Похоже, было бы более уместно объявить метод следующим образом:
Javapublic <t super e> t [] toarray (t [] a);
Тем не менее, синтаксис, как <T Super E>, не существует на Java. И даже если это существует, это не работает для массивов. Именно по этой причине при использовании этого метода, даже если T является родительским классом E или T такой же, как E, java.lang.arraystoreexception 5, 6, 7 нельзя полностью избежать. Пожалуйста, смотрите следующие два кода. В первом коде T является родительским классом E, а во втором коде T такой же, как E. оба исключения для броска кода.
Код 1:
List <Integer> intlist = new ArrayList <Integer> (); intlist.add (1); intlist.add (2); Float [] floatarray = new Float [2]; // float - это подкласс числа, поэтому float [] является подклассом числа [] number [] numarray = floatarray; // Следующее утверждение будет выбрать исключение ArrayStoreException numarray = intlist.toarray (Numarray);
Код 2:
Список <Cumber> intlist = new ArrayList <Cumber> (); // Тип списка - номер. Но число является абстрактным классом, и может хранить только экземпляры своего подкласса intlist.add (new Integer ()); intlist.add (new Integer ()); Float [] floatArray = new Float []; // float - это подкласс числа, поэтому float [] является подклассом числа [] number [] numarray = floatarray; // Следующее утверждение будет выбрать исключение ArrayStoreException numarray = intlist.toarray (Numarray);
Все вышеупомянутые исключения вызваны этим фактом: если A является родительским классом B, то [] является родительским классом B []. Все классы в Java наследуют от объекта, а Object [] - родительский класс всех массивов.
Этот пост 8 приводит пример, показывающий, что даже если тип этого метода объявлен как E, нельзя избежать ArraystoreException.
Это исключение также упоминается в документации для этого метода:
ArrayStoreException Если тип времени выполнения указанного массива не является супертипом типа времени выполнения каждого элемента в этом списке.
3 Он может быть совместимы с версиями перед Java 1.5
Этот метод появился до введения дженериков в Java (дженерики были введены в JDK1.5). Это было объявлено в то время:
Javapublic Object [] toarray (Object [] a)
После того, как генерики появляются, многие классы и методы становятся общими. Этот метод также объявляет это так:
Javapublic <t> t [] toarray (t [] a)
Это объявление совместимо с версиями до Java 1.5.
4 еще несколько слов
Этот метод требует параметра массива. Если длина этого массива больше или равна размеру текущего списка, элементы в списке будут храниться в массиве; Если длина этого массива меньше размера текущего списка, будет создан новый массив, и элементы в текущем списке будут храниться в недавно созданном массиве. Чтобы повысить эффективность, если возможно, длина пройденного массива должна быть больше или равна размеру списка, чтобы избежать создания нового массива этим методом.
List <Integer> intlist = new ArrayList <Integer> (); intlist.add (); intlist.add (); // вставить в массив, его длина - число [] numarray = intlist.toarray (новый номер []); // оператор // Вставьте в массив, его длина равна длине числа intlist [] numarray = intlist.toarray (новый номер [intlist.size ()]); //Заявление
Кроме того, массив в виде параметров не может быть нулевым, в противном случае будет брошено NullpointerException.
Сноски:
1
Эффективная Java (2 -е издание)
2
Связь
3
Связь
4
Связь
5
Связь
6
Связь
7
Связь
8
Связь
9
Связь
10
Связь
Создано: 2016-04-06 Ср 21:14
EMACS 24.5.1 (режим орг 8.2.10)
Проверять
Приведенное выше содержание является причиной, по которой метод типа параметров Java ArrayList.toarray (t []), представленный вам редактором, является T, а не E. Я надеюсь, что это будет полезно для всех!