Параметризованных Типов Java Подстановочные Знаки С Несколькими Классами


Я хочу иметь объект класса, но я хочу заставить любой класс, который он представляет, расширить класс A и реализовать интерфейс B.

Я могу сделать:

Class<? extends ClassA>

или:

Class<? extends InterfaceB>

но я не могу сделать и то и другое. Есть ли способ сделать это?

2 328

2 ответа:

вообще-то, ты можете делай, что хочешь. Если вы хотите предоставить несколько интерфейсов или интерфейсы класса plus, вы должны иметь свой подстановочный знак выглядеть примерно так:

<T extends ClassA & InterfaceB>

посмотреть Дженерики Учебник at sun.com в частности,Параметры Ограниченного Типа раздел, в нижней части страницы. Вы можете фактически перечислить более одного интерфейса, если хотите, используя & InterfaceName для каждого, что вам нужно.

этот может получиться сколь угодно сложно. Чтобы продемонстрировать, см. объявление JavaDoc Collections#max, который (завернутый в две строки) является:

public static <T extends Object & Comparable<? super T>> T
                                           max(Collection<? extends T> coll)

почему так сложно? Как сказано в Java Generics FAQ:для сохранения бинарной совместимости.

похоже, что это не работает для объявления переменных, но это работает при установке общей границы на класс. Таким образом, чтобы сделать то, что вы хотите, вам, возможно, придется прыгать через несколько обручей. Но вы можете сделать его. Вы можете сделать что-то вроде этого, поставив общую границу на свой класс, а затем:

class classB { }
interface interfaceC { }

public class MyClass<T extends classB & interfaceC> {
    Class<T> variable;
}

и variable это имеет ограничение, которое вы хотите. Для получения дополнительной информации и примеров, проверь Страница 3 дженерики в Java 5.0. Заметьте, в <T extends B & C>, имя класса должно быть первым,и интерфейсы следуют. И конечно, вы можете только один класс.

вы не можете сделать это с "анонимными" параметрами типа (т. е. подстановочными знаками, которые используют ?), но вы можете сделать это с "именем" параметры типа. Просто объявите параметр типа на уровне метода или класса.

import java.util.List;
interface A{}
interface B{}
public class Test<E extends B & A, T extends List<E>> {
    T t;
}