繁体   English   中英

自引用泛型类型

[英]Self-referential Generic Types

考虑这个例子:

public final class Main<T extends Main<T>> {

    public static void main(String[] args) {
        Main<?> main = new Main<>();
    }
}

这完全编译。 但是当我尝试在不使用菱形的情况下进行编译时,我能够使用它的唯一方法是使用原始类型。

Main<?> main = new Main();    

没有原始类型的尝试不起作用:

Main<?> main = new Main<?>();              // None of
Main<?> main = new Main<Main<?>>();        // these
Main<?> main = new Main<Main<Main<?>>>();  // compile

那么为什么钻石的原始版本有效呢? 当您编写Main<?> main = new Main<>();时,推断类型是什么Main<?> main = new Main<>();

它是推断原始类型,还是推断某种无限嵌套类型?

Main<Main<Main<Main<...>>>>

? Main<?>是占位符,在绑定时可以是任何类型。

每个? 您在源代码中编写的内容可能是不同的类型(在错误消息中称为capture#2-of ? ),因此您无法将Main<?>的表达式分配给任何可表达类型的变量。

钻石操作员在这里工作,因为它的类型推断在?之后运行? s被捕获 - 您的Main<>变为Main<?>但是Main<capture#1 of ?> (假设您将其分配给Main<?>capture#1 )。

换句话说,菱形运算符是唯一可以直接指定特定捕获的语法,就像var中的var是唯一可以直接指定匿名类型的语法。 (请注意,使用方法类型推断的重载解析也可以解析为特定捕获)


至于代码的含义, new Main<?>() (对于任何捕获? )是Main<? extends Object>缩写Main<? extends Object> Main<? extends Object> ,或者,在您的情况下, Main<? extends Main<same ?>> Main<? extends Main<same ?>> (编译器自动将?约束到类型的约束)。 这成为Main<>的协变视图,其中type参数只能转换为Main<?> (因为它实际上可能是任何类型,所以你不能假设超出约束的任何东西)。

通常,没有理由真正创造这样的东西。

通过使用通用的辅助方法,可以在没有菱形运算符的情况下编译一些东西(当然,这会引发一个问题,即调用辅助方法的类型参数是什么):

final class Main<T extends Main<T>> {

    public static void main(String[] args) {
        Main<?> main = helper();
    }
    private static <T extends Main<T>> Main<T> helper() {
        return new Main<T>();
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM