Рассмотрим следующую функцию Java:
public void foo(Class<? extends Exception> cl, List<? extends Exception> ls) throws Exception {
ls.add(cl.newInstance());
}
Это не работает, поскольку захват типов cl
и ls
не унифицирован и может, действительно, ссылаться на разные типы. Если бы эта функция компилировалась, я мог бы вызвать ее как foo(NullPointerException.class, new List
, что было бы незаконно.
Мы можем исправить это, очевидно, путем унификации захвата типов, например, так:
public <T extends Exception> void foo(Class<T> cl, List<T> ls) throws Exception {
ls.add(cl.newInstance());
}
Теперь эта функция работает, как и ожидалось. Таким образом, переходим к моему вопросу: Есть ли способ унифицировать захват типов в рамках одного объявления типа?
Например, я часто сталкиваюсь с тем, что мне нужна карта, которая сопоставляет классы с их экземплярами. Единственный способ, который я могу придумать в настоящее время, это иметь сопровождающую функцию, которая делает непроверенные приведения:
private Map<Class<? extends Foo>, ? extends Foo> map = ...;
@SuppressWarnings("unchecked")
private <T extends Foo> T getFoo(Class<T> cl) {
return((T)map.get(cl));
}
Но было бы, конечно, приятнее не подавлять предупреждения, а просто заставить компилятор понять, что два приведения типа в объявлении типа map должны быть одинаковыми, а затем просто сделать map публичным. Например, если бы я мог иметь объявление, подобное следующему:
<T extends Foo> Map<Class<T>, T> map = ...;
Очевидно, что это неправильный синтаксис, но мой вопрос сводится к следующему: Есть ли какой-нибудь правильный синтаксис, который позволил бы мне сделать что-то подобное?