Аргументы универсального типа Java

java generics

27375 просмотра

3 ответа

У меня есть метод, который принимает List<?>в качестве аргумента.

public static String method(List<?> arg){
     // Do something based on type of the list
}

//I call the method as below
List<ClassA> listA = new ArrayList<ClassA>();
List<ClassB> listB = new ArrayList<ClassB>();
method(listA);
method(listB);

В method, как я знаю , если argэто Listиз ClassAили Listв ClassB?

Автор: user682765 Источник Размещён: 12.11.2019 09:43

Ответы (3)


4 плюса

Решение

Из ответа пользователя под названием Romain «Если вы используете , Вы имеете в виду, что вы не собираетесь нигде использовать параметризованный тип. Либо перейдите к определенному типу (в вашем случае это кажется List ), либо к очень общий список "

Кроме того, я считаю, что если вы используете вопросительный знак, компилятор не будет отлавливать несоответствия типов до времени выполнения (reified; p.119 Effective Java), обходя стирание и эффективно используя преимущества, которые вы получаете от использования универсальных типов ???

Чтобы ответить на вопрос спрашивающего: если вы используете List , а затем пытаетесь привести его к A или B, возможно, используя instanceOf, это может быть способом определить, что это такое. Бьюсь об заклад, есть лучший способ сделать это, чем это все же.

Автор: djangofan Размещён: 13.04.2012 10:31

18 плюса

Технически говоря, вы МОЖЕТЕ использовать, instanceofчтобы проверить, является ли объект определенного типа.

Однако ... Это НЕ хорошая идея.

Способ, которым вы объявили свой метод, может принимать список любого типа, поэтому это не обязательно будет A или B.

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

Вы можете сделать это так:

public static <T> String method(List<T> arg) {
    // We now know that the type of the list is T, which is
    // determined based on the type of list passed to this
    // method.  This would demonstrate the point better if
    // the return type was T, but I'm leaving the return type
    // as String, because that's what your code returns.
}

Вот лучший пример :

Если вы хотите создать универсальный метод, который возвращает первый элемент списка, вы должны сделать это так:

public static <T> T firstElement(List<T> theList) {
    if (theList == null) {
        return null;
    }
    T objectOfTypeT = theList.get(0);
    return objectOfTypeT;
}

Обратите внимание, что тип возвращаемого значения сейчас T.

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

Обычно вы просто возвращаетесь theList.get(0), но я добавил строку, чтобы сделать назначение дженериков более очевидной.

Объяснение синтаксиса:

  • <T>Указывает на то, что этот метод имеет один тип параметра имени Т.

  • T, Что непосредственно следует тип возврата (так же , как вы обычно возвращают String, Integer, и т.д. ...).

  • Параметр Tв List - это то, как компилятор знает, что это за хрень T.

Это позволяет компилятору сказать: « Этот метод ожидает что-то типа T. О, смотрите ... Список также имеет тип T. Если кто-то передает список строк этому методу, то T должен быть строкой. Если кто-то передает список целых чисел для этого метода, T должен быть целым числом. "

Напротив, ваш метод может возвращать только String, и он не знает, какой тип используется в List.


Также...

Если A и B расширяют один и тот же класс с именем TheParentClass, вы можете объявить свой метод следующим образом:

public static String method(List<? extends TheParentClass> arg)

Таким образом, вы узнаете немного больше о возможных типах вашего параметра (и сможете извлечь пользу из проверки типов во время компиляции).

Автор: jahroy Размещён: 13.04.2012 10:38

1 плюс

Учитывая ваш пример, нет способа узнать, каковы аргументы универсального типа List. Они стираются на уровне экземпляра.

Автор: oconnor0 Размещён: 13.04.2012 10:31
Вопросы из категории :
32x32