代码之家  ›  专栏  ›  技术社区  ›  Daniel

Java类型推理何时产生无限类型?

  •  11
  • Daniel  · 技术社区  · 15 年前

    JLS在类型推断算法(_§15.12.2)中提到:

    上面的过程可能产生无限类型。这是允许的, Java编译器必须识别这些情况,并使用循环数据结构来适当地表示它们。

    然而,我找不到一个实际的例子,在这个例子中javac生成了一个无限类型。 我认为在下列情况下应该生产一个:

    <T> T pick(T a, T b) { ... }
    
    pick("string", 3);
    

    字符串和整数都是可比较的<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(字符串,整数) 应为无限类型。Javac好像错了。也许它根本不实现无限类型?

    2 回复  |  直到 15 年前
        1
  •  9
  •   Vladimir Reshetnikov    15 年前

    下面的代码将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
  •  -1
  •   Buhake Sindi Tesnep    15 年前

    无限类型的可能性可以是(例如,地图中的地图对象、地图中的地图对象等)。

    Map<? extends Serializable, Map<? extends Serializable, Map<? extends Serializable, Map<? extends Serializable, Map<? extends Serializable, Map>>>>> objectMap;
    

    (这是为了可读性而对深度5进行的……但是您可以在无限深的地图中添加地图。

    我不知道你在找什么……