Когда вывод типа Java порождает бесконечный тип?
JLS упоминает в алгоритме вывода типа (§15.12.2):
Возможно, что вышеописанный процесс дает бесконечный тип. Это допустимо, и компиляторы Java должны распознавать такие ситуации и представлять их соответствующим образом с использованием циклических структур данных.
Однако я не могу найти фактический пример, где javac создает бесконечный тип.
Я думаю, что это должно привести к следующему:
<T> T pick(T a, T b) { ... }
pick("string", 3);
И String, и Integer являются Comparable <themselve> , поэтому их общий супертип должен быть Comparable<? extends Comparable<? extends Comparable<? ...>>>
(бесконечным).
Я могу сделать:
Comparable<? extends Comparable<?>> x = pick("string", 3);
но затем я попробовал:
Comparable<? extends Comparable<? extends Comparable<?>>> x = pick("string", 3);
и это не компилируется.
Кажется, что рекурсия прерывается после двух шагов.
Знаете ли вы о любом случае, чтобы заставить Java фактически создавать бесконечный тип?
-
Изменить: похоже, что это ошибка компилятора. Читая спецификацию, давайте посмотрим, как работает расчет lub(String, Integer)
:
ST(String) = { String, Comparable<String>, Serializable, CharSequence, Object }
ST(Integer) = { Integer, Comparable<Integer>, Serializable, Number, Object }
EC = { Comparable, Serializable, Object }
MEC = { Comparable, Serializable }
Inv(Comparable) = { Comparable<String>, Comparable<Integer> }
lcta(String, Integer) = ? extends lub(String, Integer)
lci(Inv(Comparable)) = Comparable<? extends lub(String, Integer)>
lub(String, Integer) = Serializable & Comparable<? extends lub(String, Integer)>
Итак, lub(String, Integer)
должен быть бесконечным. Кажется, Джавак здесь не прав. Может быть, он не реализует бесконечные типы?
Ответы
Ответ 1
Следующий код отправляет javac в бесконечный цикл. Предположительно, он пытается построить бесконечный тип, но не может представлять его как конечную циклическую структуру данных.
interface I<T> {}
interface A<T> extends I<A<A<T>>>{}
abstract class X {
abstract <T> T foo(T x, T y);
void bar(A<Integer> x, A<String> y){
foo(x, y);
}
}
Ответ 2
Возможность бесконечных типов может быть (например, объектом карты внутри карты внутри карты и т.д.
Map<? extends Serializable, Map<? extends Serializable, Map<? extends Serializable, Map<? extends Serializable, Map<? extends Serializable, Map>>>>> objectMap;
(Это делается для глубины 5 для удобочитаемости... но вы можете добавлять карты внутри карты бесконечно глубоко.
Я не знаю, что вы ищете....