根据 JLS §15.2.12.1:
- 如果方法调用包括显式类型参数,并且成员是泛型方法,则类型参数的数量等于方法的类型参数的数量。
此子句意味着非泛型方法可能适用于提供显式类型参数的调用。事实上,它可能被证明是适用的。在这种情况下,类型参数将被忽略。
其次是正当理由
这一规则源于兼容性问题和可替代性原则。由于接口或超类可以独立于其子类型进行生成,因此我们可以用非泛型方法覆盖泛型方法。但是,重写(非泛型)方法必须适用于对泛型方法的调用,包括显式传递类型参数的调用。否则,子类型将无法替代其生成的超类型。
沿着这条推理路线,让我们构建一个示例。假设在Java 1.4中,JDK有一个类
public class Foo
{
/** check obj, and return it */
public Object check(Object obj){ ... }
}
某些用户编写了一个专有类,用于扩展和重写该方法Foo
check
public class MyFoo extends Foo
{
public Object check(Object obj){ ... }
}
当Java 1.5引入泛型时,被归纳为Foo.check
public <T> T check(T obj)
雄心勃勃的向后可比性目标要求仍然在Java 1.5中编译而无需修改;并且仍然是 的重写方法。MyFoo
MyFoo.check[Object->Object]
Foo.check[T->T]
现在,根据上述理由,由于编译:
MyFoo myFoo = new MyFoo();
((Foo)myFoo).<String>check("");
这也必须编译:
myFoo.<String>check("");
即使不是通用的。MyFoo.check
这听起来像是一个延伸。但即使我们接受这个论点,解决方案仍然过于宽泛和过分。JLS可以收紧它,这样就是非法的,因为类型参数arity不匹配。他们可能没有时间解决这个问题,所以他们只是走了一条简单的路线。myFoo.<String,String>check
obj.<Blah>toString()