<?> против <T> - PullRequest
       34

<?> против <T>

7 голосов
/ 29 марта 2009

Я наткнулся на функцию, похожую на эту:

public void function(Class<?> clazz) {...}

Каковы плюсы / минусы изменения метода на:

public <T> void function(Class<T> clazz) {...}

edit: каковы различия времени компиляции / времени выполнения.

Ответы [ 4 ]

10 голосов
/ 29 марта 2009

Использование "?" такой же, как «любой», тогда как «Т» означает «определенный тип». Итак, сравните эти интерфейсы:

public interface StrictClass<T> {
 public T doFunction(Class<T> class);
}

public interface EasyClass<T> {
 public > doFunction(Class<?> class);
}

Теперь мы можем создавать классы:

public class MyStrictClass implements StrictClass<String> {
  public String doFunction(Class<String> stringClass) {
    //do something here that returns String
  }
}

public class MyEasyClass implements EasyClass<String> {
  public String doFunction(Class<?> anyClass) {
    //do something here that returns String
  }
}

Надеюсь, это поможет!

7 голосов
/ 30 марта 2009

todd.run полностью прав, но это только половина ответа. Существуют также варианты использования для выбора <T> вместо <?> (или наоборот), которые применяются, когда вы не добавляете параметр типа в класс, который включает метод. Например, рассмотрим разницу между

public <E extends JLabel> boolean add(List<E> j) {
    boolean t = true;
    for (JLabel b : j) {
        if (b instanceof JLabel) {
            t = t && labels.add(b);
        }
    }
    return t;
}

и

public boolean add(List<? extends JLabel> j) {
    boolean t = true;
    for (JLabel b : j) {
        if (b instanceof JLabel) {
            t = t && labels.add(b);
        }
    }
    return t;
}

Первый метод на самом деле не будет компилироваться, если вы не добавите соответствующий параметр типа в класс включения, тогда как второй метод будет компилироваться независимо от того, имеет ли класс включения параметр типа. Если вы не используете <?>, то вы несете локальную ответственность за указание компилятору, как получить тип, который будет заполнен буквой, используемой вместо него. Вы часто сталкиваетесь с этой проблемой - нужно использовать? а не T - при попытке написать универсальные методы, которые используют или нуждаются в «extends» и «super». Лучшее, но более сложное решение этой проблемы - на стр. 18 учебного пособия Дженида Брачи (PDF) . Также см. этот вопрос о переполнении стека , ответ на который освещает эти проблемы.

Проверьте эту ссылку переполнения стека для получения информации о вашем втором вопросе: Обобщения Java - стирание типа - когда и что происходит . Хотя я не знаю ответа на ваш вопрос о разнице во времени компиляции между <?> и <T>, я почти уверен, что ответ можно найти на этом FAQ , который Эриксон упомянул в этом посте. .

2 голосов
/ 29 марта 2009

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

ОБНОВЛЕНИЕ: о, и T можно использовать для связывания типов вместе: если Class<T> используется в разных частях функции, он будет ссылаться на один и тот же класс, но не Class<?>.

0 голосов
/ 30 марта 2009

Хороший ресурс может быть таким: http://sites.google.com/site/io/effective-java-reloaded Интересная часть, связанная с вашим вопросом, начинается примерно на 5 минуте. Просто в зависимости от того, что говорили предыдущие пользователи.

Надеюсь, это поможет:]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...