Подтвердить что ты не робот

Java Generics: множественные границы

У меня есть этот код:

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

4b9b3361

Ответ 1

Когда вы создаете экземпляр следующим образом:

GenericTest gt = new GenericTest() 

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

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

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

class GenericTest<T extends List & Date> { }

Ответ 2

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