Метод, который работает с любыми аспектами стирания List и Generics/Type Erasure.

Сначала некоторый код (Java 7), созданный только для иллюстрации моих вопросов.

import java.util.*;

class Generics101 {



    public static void addTrue(List list) {
        list.add(true);
    }

    public static void main(String[] args) {
        List<Integer> testList = new ArrayList<>();

        addTrue(testList);
        System.out.println(testList.get(0));

        // testList.add(true);  // will not compile when uncommented

    }
}

У меня есть следующие два вопроса:

  1. В методе addTrue Eclipse намекает, что ему не нравится raw types. Когда я пытаюсь изменить параметры метода, чтобы использовать подстановочный знак List<?> list, он не будет компилироваться. Я просмотрел учебник по универсальным технологиям, но не смог найти ответ. Что мне здесь не хватает и где мне об этом прочитать?

  2. В том же руководстве говорится, что "универсальные методы были введены в язык Java, чтобы обеспечить более тщательную проверку типов во время компиляции..." Я понимаю, что из-за type erasure такое принудительное выполнение не может произойти во время выполнения, поэтому мой вышеприведенный код компилируется и запускается. Это вызовет ошибку компиляции, если закомментированная строка будет раскомментирована, поэтому я предполагаю, что tighter type checks действуют в рамках одного и того же метода. Какова точная сфера применения такого правоприменения? Как это формально определяется?


person PM 77-1    schedule 24.10.2013    source источник
comment
addTrue должен работать только для List<Boolean>.   -  person Louis Wasserman    schedule 24.10.2013


Ответы (1)


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

Он не будет компилироваться, потому что вы не можете ничего добавить в файл List<?>. Потому что вы не знаете, какой тип List на самом деле придет. Например, возьмем только ваш текущий случай. Вы проезжаете List<Integer>. Он будет успешно передан List<?>. Без вопросов. Но вы добавляете к нему true, тип boolean. Если бы компилятор разрешил это, он выдал бы ClassCastException во время выполнения. Итак, это не разрешено.

поэтому я предполагаю, что в рамках того же метода действуют более строгие проверки типов. Какова точная сфера применения такого правоприменения?

Нет, это не так. Дело не в том, что проверки типов выполняются в определенной области. Он применяется везде, где используются дженерики. Ваш текущий код не будет компилироваться, если он используется с правильными дженериками, потому что вы пытаетесь добавить тип boolean к типу List<Integer>. Почему вы ожидаете, что это сработает?

Попробуйте изменить свой метод на общий метод, и вы увидите, что он не скомпилируется:

public static <T> void addTrue(List<T> list) {
    list.add(true);  // Won't compile
}

Я просмотрел учебник по дженерикам, но не смог найти ответ. Что мне здесь не хватает и где мне об этом прочитать?

Ну, это стандартный учебник от Oracle. И это то, где вы должны прочитать. Кроме того, вы также можете ознакомиться с действительно хорошей коллекцией руководств по дженерикам на странице Java Generics FAQs - Angelika. Лангер.

person Rohit Jain    schedule 24.10.2013
comment
Спасибо за ваш ответ. Что вы подразумеваете под если используется с правильными дженериками? - person PM 77-1; 24.10.2013
comment
@ PM77-1 Означает правильное использование дженериков. Например, если вы сделаете свой метод универсальным, тогда этот код не сможет скомпилироваться, если вы передадите что-либо, кроме List<Boolean>. - person Rohit Jain; 24.10.2013
comment
Re: <T> void. Я предполагал, что <T> представляет тип результата метода и, следовательно, несовместим с void. - person PM 77-1; 24.10.2013
comment
@ PM77-1 Нет, <T> представляет параметр типа для этого метода. Вы можете перейти по ссылке на учебник по дженерикам в конце моего ответа. - person Rohit Jain; 24.10.2013
comment
Спасибо. Кажется, я получил эту роль сейчас. - person PM 77-1; 24.10.2013
comment
Кроме того, очень хорошей практикой является создание копии параметра метода, внесение в него изменений и возврат измененного параметра. Согласитесь, что нельзя применять это правило каждый раз, но всегда лучше, когда это возможно. - person Shaun; 25.10.2013