Java 未对照上界类型参数检查下界通配符

Java 未对照上界类型参数检查下界通配符,java,generics,bounded-wildcard,Java,Generics,Bounded Wildcard,我想知道为什么这段代码能够成功编译 源代码: abstract class A<K extends Number> { public abstract <M> A<? super M> useMe(A<? super M> k); } 抽象类A { 公共抽象A向第一个示例中添加不会添加编译器关心的任何内容。请记住,如果我们说“M是数字的子类型”和“该类型是M的超类型”,那么实际上我们并不是说该类型是否是数字的子类型 举个更好的例子,hav

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

源代码:

abstract class A<K extends Number>
{
    public abstract <M> A<? super M> useMe(A<? super M> k);
}
抽象类A
{
公共抽象A向第一个示例中添加
不会添加编译器关心的任何内容。请记住,如果我们说“M是数字的子类型”和“该类型是M的超类型”,那么实际上我们并不是说该类型是否是数字的子类型

举个更好的例子,have
M
be
Integer
,变量的类型为
a
。虽然这显然不起作用,但它正确地满足了函数的所有要求


由于没有办法修复函数定义,它只是让函数通过,并假设调用站点会发现问题。

这是一段毫无意义的代码

它所说的就是类
A
接受一个泛型
K
,它是一个
Number
,还有一个方法
useMe
,它返回一个
A
,对
T
有一些无意义的额外限制(显然不是
Number

这里有一个实现来说明sugar所说的话是多么少:

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;
    }

}
抽象类A{

public abstract A上讨论了此编译器行为。最初,Eclipse编译器对您示例中的表达式出错,而javac没有。虽然我还没有直接搜索JLS,但一致认为规范中没有要求根据类型参数绑定检查下限通配符s、 在这种情况下,最终由调用者分配满足约束的类型(正如Stephan Herrmann在那篇文章中推测的那样)。

问题有两个部分:

第1部分:什么是

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

第2部分:


泛型类型必须完全匹配。原因可以归结为这样一个事实:如果
B
a
的子类型,
SomeClass
不是
SomeClass
的子类型,更具体地说,
SomeClass
不是
SomeClass的子类型,两者都是不同的,那么为什么要编译呢?我知道sy的意思mbols.@SotiriosDelimanolis:很抱歉,你是对的,我的第一个答案不完整,我仔细考虑了一下,然后想出了一个更好的答案。如果包含从编译器收到的实际错误消息,你可能会得到更好的答案。(我们不必启动IDE来理解你的问题。)实际的错误消息是什么?问题是为什么要编译?请注意,对于那些好奇的人来说,将
替换为
也可以编译。为了这个问题,似乎可以将返回类型替换为void。我想这个问题的唯一真正答案是“因为编译器不够聪明,不应该允许这样做”。你确定javac不会吗!我的NetBeans也一直报告这个异常。@Sage它在Eclipse(1.7)和javac(sun jdk 1.7)中为我编译Ideone:.您的Netbeans设置为什么编译器?@Sage我有Netbeans 7.4,第一个示例也为我编译。JDK 1.7@Pawel,是的,但问题在第二个示例下,与第一个示例的区别在于标记
*为什么?*
:);)@Sage实际上问题是为什么第一个示例会编译。
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;
    }

}