2015-05-20 2 views
13

У меня есть этот код:Java Дженерики: Несколько Bounds

public class Test { 

    public static void main(String[] args) { 
     Test t = new Test(); 
     t.callTest(); 
    } 

    public void callTest() { 
     GenericTest gt = new GenericTest<Date>(); // this line don't compile 
     gt.test(new Date()); 
    } 

    class GenericTest<T extends Date & List> { 
     T x; 

     public void test(T y) { 
      System.out.println(x.toString()); 
     } 
    } 
} 

Я понимаю, почему new GenericTest<Date>() не компилируется, это потому, что дата не реализует интерфейс List, но если я создаю экземпляр GenericTest gt = new GenericTest() без родового, в целом код работает, и я не понимаю, почему. Тест метода ожидает (T y), где T extends Date и реализует List, но он работает с gt.test(new Date()).

ответ

16

При создании экземпляра так:

GenericTest gt = new GenericTest() 

использовать сырую версию GenericTest типа. Это означает, что тип T будет заменен его первой привязкой (в вашем случае Date). Вот почему в контракте метода GenericTest#test() есть параметр Date, но не List.

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

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

class GenericTest<T extends List & Date> { } 
+0

Действительно ли границы имеют значение при использовании необработанных типов? – CKing

+1

Да, они имеют значение. Если у вас есть только '' (то есть параметр типа без ограничений), то заменой будет 'Object', однако если у вас' 'T extends Number>', то заменой будет 'Number'. –

+1

Вы правы. Применяется первая граница. Просто попробовал. +1 – CKing

-2

Если создать общие экземпляр класса без общих параметров компилятор дает предупреждение и больше не контролирует использование созданного экземпляра. Что касается того, почему код работает без объявления родового типа, поскольку в этом случае T считается объектом, то есть любым типом является хорошим

+0

'T предполагается объектом Object. Я считаю, что это неверно. См. Ответ от @kocko – CKing

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