Java 具有有界通配符类型varargs的方法如何编译?

Java 具有有界通配符类型varargs的方法如何编译?,java,generics,bounded-wildcard,Java,Generics,Bounded Wildcard,我对这个例子的工作原理摸不着头脑,似乎打印得很恰当 公共类测试{ 静态类形状{ 公共字符串toString(){ 返回“形状”; } } 静态类圆扩展形状{ 公共字符串toString(){ 返回“圈”; } } 静态类方形扩展形状{ 公共字符串toString(){ 返回“正方形”; } } publicstaticvoidwildcardvarargs(ThreadLocal基本上,即使删除了类型,也会得到以下结果: .... public static void wildCardVarAr

我对这个例子的工作原理摸不着头脑,似乎打印得很恰当

公共类测试{
静态类形状{
公共字符串toString(){
返回“形状”;
}
}
静态类圆扩展形状{
公共字符串toString(){
返回“圈”;
}
}
静态类方形扩展形状{
公共字符串toString(){
返回“正方形”;
}
}

publicstaticvoidwildcardvarargs(ThreadLocal基本上,即使删除了类型,也会得到以下结果:

....
public static void wildCardVarArgs(ThreadLocal... list) {
    for (ThreadLocal s : list) {
        Object o = s.get(); //Compiler knows there's "at least" Object inside
        System.out.println(o.toString()); //And all Objects have "toString"
    }
}
....
因此,无论您在其中推送什么,所有对象的基类,即Object,都有一个方法toString,在您的情况下,该方法被重写。因此,在对象类型变量上调用它永远不会失败,在您的情况下,调用被重写的方法


添加:

现在,如果您在Shape类中添加了一些新方法,会发生以下情况:

public static void wildCardVarArgs(ThreadLocal<? extends Shape>... list) {
    for (ThreadLocal<? extends Shape> s : list) {
        Shape o = s.get(); //Compiler knows there's "at least" Shape inside
        System.out.println(o.someCustomMethod()); //And all Shapes have "someCustomMethod", does not matter if it is overriden or not
    }
}

但是,Java并不真正在意。它希望在编译时能正确地找到所有错误,因此在运行时不会发生此类错误(spoiler:如果不小心的话,它们确实会时不时地发生)。

基本上,即使您删除了类型,也会得到以下结果:

....
public static void wildCardVarArgs(ThreadLocal... list) {
    for (ThreadLocal s : list) {
        Object o = s.get(); //Compiler knows there's "at least" Object inside
        System.out.println(o.toString()); //And all Objects have "toString"
    }
}
....
因此,无论您在其中推送什么,所有对象的基类,即Object,都有一个方法toString,在您的情况下,该方法被重写。因此,在对象类型变量上调用它永远不会失败,在您的情况下,调用被重写的方法


添加:

现在,如果您在Shape类中添加了一些新方法,会发生以下情况:

public static void wildCardVarArgs(ThreadLocal<? extends Shape>... list) {
    for (ThreadLocal<? extends Shape> s : list) {
        Shape o = s.get(); //Compiler knows there's "at least" Shape inside
        System.out.println(o.someCustomMethod()); //And all Shapes have "someCustomMethod", does not matter if it is overriden or not
    }
}

但是,Java并不真正在意。它希望在编译时能正确地找到所有错误,因此在运行时不会发生此类错误(spoiler:如果不小心的话,它们确实会时不时地发生)。

基本上,即使您删除了类型,也会得到以下结果:

....
public static void wildCardVarArgs(ThreadLocal... list) {
    for (ThreadLocal s : list) {
        Object o = s.get(); //Compiler knows there's "at least" Object inside
        System.out.println(o.toString()); //And all Objects have "toString"
    }
}
....
因此,无论您在其中推送什么,所有对象的基类,即Object,都有一个方法toString,在您的情况下,该方法被重写。因此,在对象类型变量上调用它永远不会失败,在您的情况下,调用被重写的方法


添加:

现在,如果您在Shape类中添加了一些新方法,会发生以下情况:

public static void wildCardVarArgs(ThreadLocal<? extends Shape>... list) {
    for (ThreadLocal<? extends Shape> s : list) {
        Shape o = s.get(); //Compiler knows there's "at least" Shape inside
        System.out.println(o.someCustomMethod()); //And all Shapes have "someCustomMethod", does not matter if it is overriden or not
    }
}

但是,Java并不真正在意。它希望在编译时能正确地找到所有错误,因此在运行时不会发生此类错误(spoiler:如果不小心的话,它们确实会时不时地发生)。

基本上,即使您删除了类型,也会得到以下结果:

....
public static void wildCardVarArgs(ThreadLocal... list) {
    for (ThreadLocal s : list) {
        Object o = s.get(); //Compiler knows there's "at least" Object inside
        System.out.println(o.toString()); //And all Objects have "toString"
    }
}
....
因此,无论您在其中推送什么,所有对象的基类,即Object,都有一个方法toString,在您的情况下,该方法被重写。因此,在对象类型变量上调用它永远不会失败,在您的情况下,调用被重写的方法


添加:

现在,如果您在Shape类中添加了一些新方法,会发生以下情况:

public static void wildCardVarArgs(ThreadLocal<? extends Shape>... list) {
    for (ThreadLocal<? extends Shape> s : list) {
        Shape o = s.get(); //Compiler knows there's "at least" Shape inside
        System.out.println(o.someCustomMethod()); //And all Shapes have "someCustomMethod", does not matter if it is overriden or not
    }
}

然而,Java并不真正在意。它希望在编译时能够正确地找到所有错误,因此在运行时不会发生此类错误(扰流板:如果不小心的话,它们确实会时不时地发生)。

擦除与否,
s.get()
将获得一个
正方形/圆形
对象,并将调用被重写的
toString
。如果从代码中删除所有泛型,只需到处使用原始类型,您就可以看到为什么它在运行时工作得很好。擦除与否,
s.get()
将获得一个
正方形/圆形
对象,并将调用被重写的
toString
。如果从代码中删除所有泛型,只需到处使用原始类型,您就可以看到为什么它在运行时工作得很好。擦除与否,
s.get()
将获得一个
正方形/圆形
对象,并将调用被重写的
toString
。如果从代码中删除所有泛型,只需到处使用原始类型,您就可以看到为什么它在运行时工作得很好。擦除与否,
s.get()
将获得一个
正方形/圆形
对象,并将调用重写的
toString
。如果从代码中删除所有泛型,只需到处使用原始类型,您可能会看到为什么它在运行时工作得很好。但是如果我添加另一个公共方法“
newMethod()
”来塑造(这不是对象类的一部分),并在子类中重载,我仍然可以执行
s.get().newMethod()
谢谢。到目前为止,从编译器的角度来看,这是有意义的。但在实际的生产代码中,我们的重载是
wildcardvargs(ThreadLocal…list)
我们对编译器如何区分两者感到困惑。啊,谢谢,运行时相信编译时一切都会正常工作。但是如果我添加另一个公共方法“
newMethod()
”来塑造(这不是对象类的一部分),并在子类中重载它,我仍然可以执行
s.get().newMethod()
谢谢。到目前为止,从编译器的角度来看,这是有道理的。但是,在实际的生产代码中,我们有一个超负荷的
通配符varargs(ThreadLocal…list)
我们对编译器如何区分两者感到困惑。啊,谢谢,运行时相信编译时一切都会正常工作。但是如果我添加另一个公共方法“
newMethod()
”来塑造(这不是对象类的一部分),并在子类中重载它,我仍然可以执行
s.get().newMethod()
谢谢。到目前为止,从编译器的角度来看,这是有道理的。但是,在实际的生产代码中,我们有一个超负荷的
通配符varargs(ThreadLocal…list)
我们对编译器如何区分两者感到困惑。啊,谢谢你,运行时相信编译时一切正常。但是如果我添加另一个公共方法“
newMethod()
”(这不是