Рубрики
Без рубрики

Java Generics – против

Изучите сходства и различия в

Автор оригинала: Sampada Wagde.

1. Обзор

В этом быстром учебнике мы увидим сходства и различия между и в Java Дженерики .

Тем не менее, это является продвинутой темой, крайне важно, чтобы получить базовое понимание этого вопроса, прежде чем погрузиться в суть вопроса.

2. Справочная информация о дженериках

Дженерики были введены в JDK 5 для устранения ошибок в компиляции времени и укрепления безопасности типа. Эта дополнительная безопасность типа устраняет литье в некоторых случаях использования и дает программистам возможность писать общие алгоритмы, оба из которых могут привести к более читаемому коду.

Например, предварительно JDK 5, мы должны работать с элементами списка с помощью литья. Это, в свою очередь, создало определенный класс ошибок времени выполнения:

List aList = new ArrayList();
aList.add(new Integer(1));
aList.add("a_string");
        
for (int i = 0; i < aList.size(); i++) {
    Integer x = (Integer) aList.get(i);
}

Теперь в этом коде есть две проблемы, которые мы хотели бы решить:

  • Нам нужен явный актерский состав, чтобы извлечь ценности из aList – тип зависит от переменного типа слева – Интегер в этом случае
  • Мы получим ошибку времени выполнения на второй итерации, когда мы пытаемся бросить a_string к целое число

Дженерики заполняют роль для нас:

List iList = new ArrayList<>();
iList.add(1);
iList.add("a_string"); // compile time error

for (int i = 0; i < iList.size(); i++) {
    int x = iList.get(i);
}

Компилятор скажет нам, что это не возможно, чтобы добавить a_string к Список типа Интегер , что лучше, чем узнать во время выполнения.

Более того, явного литья не требуется, так как компилятор уже знает, что iList держит Интегер секунда. Кроме того, из-за магии распаковки, мы даже не нуждаются в Интегер типа, его примитивной формы достаточно.

3. Подстановочные знаки в дженериках

Вопросительный знак, или подстановочный знак, используется в дженериках для представления неизвестного типа. Он может иметь три формы:

  • Неограниченные подстановочные : Список представляет собой список неизвестного типа
  • Верхние связанные wildcards : Список представляет собой список Номер или его подтипы, такие как Интегер и двойной
  • Нижние связанные wildcards : Список представляет собой список Интегер или его супер-типов Номер и объект

Теперь, с Объект является неотъемлемым супер-тип всех типов в Java, мы хотели бы поддаться искушению думать, что он также может представлять собой неизвестный тип. Другими словами, Список и Список может служить той же цели. Но они этого не делают.

Рассмотрим эти два метода:

public static void printListObject(List list) {    
    for (Object element : list) {        
        System.out.print(element + " ");    
    }        
}    

public static void printListWildCard(List list) {    
    for (Object element: list) {        
        System.out.print(element + " ");    
    }     
}

Учитывая список Интегер s, скажем:

List li = Arrays.asList(1, 2, 3);

распечататьListObject (li) не будет компиляции, и мы получим эту ошибку:

The method printListObject(List) is not applicable for the arguments (List)

В то время как РаспечататьListWildCard (li) будет компилировать и будет 1 2 3

4. и – Сходства

В приведеном выше примере, если мы изменим подпись метода для РаспечататьЛистВилдКар Кому:

public static void printListWildCard(List list)

Он будет функционировать так же, как распечататьListWildCard (список список) сделал. Это связано с тем, что Объект является супертипом всех java-объектов, и в основном все Объект . Итак, Список Интегер s обрабатывается также.

Короче говоря, это означает, что ? и ? расширяет объект являются синонимами в этом примере .

Хотя в большинстве случаев это будет справедливо, но есть несколько отличий, а также . Давайте посмотрим на них в следующем разделе.

5. и – Разница

Поддающиеся проверке типы являются те, чей тип не стирается во время компиляции. Другими словами, не поддающийся проверке представление типа будет иметь меньше информации, чем его коллега по компиляции, потому что некоторые из них будут стерты.

Как правило, параметризированные типы не поддаются переопроблему. Это означает Список и Карта не поддаются проверке. Компилятор стирает их тип и рассматривает их как Список и Карта соответственно.

Единственным исключением из этого правила являются неограниченные типы подстановочных карт. Это означает Список и Карта поддаются .

С другой стороны, Список не поддающийся . Хотя тонкие, это заметное различие.

Не поддающиеся проверке типы не могут быть использованы в определенные ситуации например, в instanceof оператора или в качестве элементов массива.

Итак, если мы напишем:

List someList = new ArrayList<>();
boolean instanceTest = someList instanceof List

Этот код компилирует и instanceTest это истинное .

Но, если мы используем instanceof оператор на Список :

List anotherList = new ArrayList<>();
boolean instanceTest = anotherList instanceof List;

затем строка 2 не компилирует.

Аналогичным образом, в приведенной ниже фрагменте строка 1 компилирует, но строка 2 не:

List[] arrayOfList = new List[1];
List[] arrayOfAnotherList = new List[1]

6. Заключение

В этом коротком учебнике мы увидели сходство и различия в и .

Хотя в основном похожи, Есть тонкие различия между ними с точки зрения их поддаются проверке или нет.