繁体   English   中英

较低有界通配符未针对上限有效类型参数进行检查

[英]Lower bounded wildcard not checked against upper bounded type parameter

我想知道为什么这段代码编译成功?

源代码:

abstract class A<K extends Number>
{
    public abstract <M> A<? super M> useMe(A<? super M> k);
}

编译成功

它是如何工作的,为什么编译? M是任何类型,为什么它可以使用? 应该是: <M extends Number> 这不会编译:

abstract class A<K extends Number>
{
    public abstract <M> A<? super M> useMe(A<M> k);
}

错误信息:

类型参数M不在类型变量K的范围内,其中M,K是类型变量:M extends方法useMe中声明的Object(A)K extends A类中声明的Number

有什么不同?

Eclipse错误讨论了此编译器行为。 最初,Eclipse编译器在您的示例中为表达式执行了错误,而javac则没有。 虽然我还没有直接搜索JLS,但是共识似乎是规范中没有任何内容要求根据类型参数边界检查较低的有界通配符。 在这种情况下,最终由调用者分配一个满足约束条件的类型(如Stephan Herrmann在该帖子中所推测的那样)。

这是一段令人惊讶的无意义的代码。

所有这一切都说A类采用的是泛型K ,它是一个Number并且有一个方法useMe返回A<T> ,对T有一些无意义的额外限制(显然不是Number )。

这是一个实现,以显示糖的说法有多少:

abstract class A<K extends Number> {
    public abstract <M> A<? super M> useMe(A<? super M> k);
}

class B extends A<Number> {

    @Override
    public <M> A<? super M> useMe(A<? super M> k) {
        // Not much more you can do here but this.
        return k;
    }

}

? super M ? super M东西只是毫无意义的gobbledegook - 所有编译器都可以从它派生的是传递给它的参数和返回的结果必须是特定未命名类的超类。

泛型可以在编译时轻松检测编码错误。 使用像这样的mumbo-jumbo只是误导混淆。

<M extends Number>添加到第一个示例不会添加编译器关心的任何内容。 请记住,如果我们说“M是数字的子类型”和“类型是M的超类型”,你说的是“M的超类型”,我们实际上并没有说这种类型是否为子类型数。

更好的例子是, MInteger ,变量为A<Object> 虽然显然不起作用,但它能正确满足功能的所有要求。

由于无法修复函数定义,它只是让它通过并假设调用站点将捕获问题。

您的问题分为两部分:

第1部分:什么是<M>

方法上存在泛型参数使其成为“类型化方法”,这意味着该方法具有由调用者确定的泛型类型,通常通过推理来确定。 它可能是有界的。 如果类也有类型,并且方法是实例方法,则这两种类型是不相关的。

第2部分:

泛型类型必须完全匹配。 原因归结为如果BA的子类型, SomeClass<T extends B>不是SomeClass<T extends A>的子类型,更具体地说, SomeClass<A>不是SomeClass<? super A>的子类型SomeClass<? super A> SomeClass<? super A>

暂无
暂无

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

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