2016-01-22 2 views
5

Я пытаюсь изучить Java Generics и нашел следующий код.Ошибки возникают при вызове печати (список <T> a, T b) с другим классом T

public static <T> void print(T a, T b){ 
    System.out.println(a); 
    System.out.println(b); 
} 

public static void main(String[] args){ 
    print(new ArrayList<String>(), 1); 
} 

который работает без проблем.

Однако, когда я меняю метод print на следующий, он дает мне компиляцию ошибок.

public static <T> void print(List<T> a, T b){ 
    System.out.println(a); 
    System.out.println(b); 
} 

Ошибка:

GenericTest.java:9: error: method print in class GenericTest cannot be applied to given types; 
    print(new ArrayList<String>(), 1); 
    ^
    required: List<T>,T 
    found: ArrayList<String>,int 
    reason: no instance(s) of type variable(s) T exist so that argument type int conforms to formal parameter type T 
    where T is a type-variable: 
    T extends Object declared in method <T>print(List<T>,T) 
1 error 

Может кто-нибудь помочь мне понять ошибки?

ответ

8

Первое, что вы должны понять, что, с помощью метода следующей сигнатурой

public static <T> void print(T a, T b) 

Оба Tдолжен быть того же типа, то есть как a, так и b будет иметь одинаковый тип.

Так почему же он работает для new ArrayList<String>() и 1? Поскольку оба параметра фактически могут быть представлены в виде Serializable, который является ближайшим общим супер тип ArrayList и Integer:

  • ArrayList реализует интерфейс Serializable.
  • 1 может быть помещен в Integer, что также является Serializable.

В этом случае компилятор выведет T как Serializable.


Во втором случае, с подписью

public static <T> void print(List<T> a, T b) 

Там нет общего супер типа T, что было бы справедливо и для List<String> и Integer. Правда, и String, и Integer - Serializable, но с generics aren't polymorphic он не работает.

+0

Можете ли вы объяснить, почему он решил 'Serializable' и не какой-либо другой общий супер тип? – Codebender

+0

@Codebender Поскольку это ближайший общий супер-тип между 'ArrayList' и' Integer'. «Объект» будет на один уровень выше в иерархии. – Tunaki

+0

Я не понимаю, как иерархия формируется между интерфейсом и классом (я задам новый вопрос об этом), но eclipse показывает, что он разрешен для Serializable (+1 для этого) ... – Codebender

5

Редактировать: Он не может быть разрешен Объектом, как я уже упоминал, но для Serializable. See Tunaki's correct answer for the reason.

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

А в вашем примере, это будет разрешится к Object Serializable, так ArrayList и Integer оба Object Serializable подтипы.

Но в вашем втором примере, у вас есть List<T> в качестве параметра ...

Теперь, когда вы называете его ArrayList<String>, тип T разрешен к String. Это не может быть разрешен к любому другому типу, потому что ArrayList<Object> ArrayList<Serializable> является НЕ супертипом ArrayList<String>

3

Вы вызываете метод в следующих способов:

print(new ArrayList<String>(), "SimpleString"); 

или

print(new ArrayList<Integer>(),5) 

потому что <T> тип, и он не может быть как строка и число одновременно.

Ваш звонок может работать, если вы делаете что-то вроде этого:

public static <T, K> void print(List<T> a, K b){ 
    System.out.println(a); 
    System.out.println(b); 
} 

public static void main(String[] args){ 
    print(new ArrayList<String>(),1); 
} 
+0

Это лучший ответ, поскольку он единственный, у которого есть код с 2 параметрами типа. Поскольку синтаксис не обязательно интуитивно понятен начинающему. В этом примере разъясняется, как его использовать. Хорошая работа. Будет +1 tommorow (лимит голосов). – HopefullyHelpful

Смежные вопросы