假设我们有两种方法,如下所示:
public static <T> T genericReturn() { /*...*/ }
public static String stringReturn() { /*...*/ }
Run Code Online (Sandbox Code Playgroud)
在调用任何方法时,无论是否有任何要求,您都可以提供类型见证:
String s;
s = Internet.<String>genericReturn(); //Type witness used in return type, returns a String
s = Internet.<Integer>stringReturn(); //Type witness ignored, returns a String
Run Code Online (Sandbox Code Playgroud)
但是我根本没有在Java中看到任何实际用途,除非无法推断出这种类型(这通常表明存在更大的问题).此外,当它没有被适当使用时被简单地忽略这一事实似乎违反直觉.那么在Java中有什么意义呢?
ars*_*jii 20
- 如果方法调用包含显式类型参数,并且成员是泛型方法,则类型参数的数量等于方法的类型参数的数量.
此子句意味着非泛型方法可能适用于提供显式类型参数的调用.实际上,它可能会变得适用.在这种情况下,类型参数将被忽略.
接下来是理由
该规则源于兼容性和可替代性原则的问题.由于接口或超类可以独立于其子类型进行泛化,因此我们可以使用非泛型方法覆盖泛型方法.但是,重写(非泛型)方法必须适用于对泛型方法的调用,包括显式传递类型参数的调用.否则,子类型不能替代其生成的超类型.
沿着这条推理,让我们构建一个例子.假设在Java1.4中,JDK有一个类
public class Foo
{
/** check obj, and return it */
public Object check(Object obj){ ... }
}
Run Code Online (Sandbox Code Playgroud)
一些用户编写了一个扩展Foo和覆盖该check方法的专有类
public class MyFoo extends Foo
{
public Object check(Object obj){ ... }
}
Run Code Online (Sandbox Code Playgroud)
当Java1.5引入泛型时,Foo.check被认为是
public <T> T check(T obj)
Run Code Online (Sandbox Code Playgroud)
雄心勃勃的后向可比性目标要求MyFoo仍然在Java1.5中编译而不进行修改; 并且MyFoo.check[Object->Object]仍然是最重要的方法Foo.check[T->T].
现在,根据上述理由,自编译以来
MyFoo myFoo = new MyFoo();
((Foo)myFoo).<String>check("");
Run Code Online (Sandbox Code Playgroud)
这也必须编译
myFoo.<String>check("");
Run Code Online (Sandbox Code Playgroud)
即使MyFoo.check不是通用的.
这听起来像一个延伸.但即使我们购买这个论点,解决方案仍然过于宽泛和过度.JLS可能已经拧紧它,以便myFoo.<String,String>check和obj.<Blah>toString()是非法的,因为类型参数参数数量不匹配.他们可能没有时间去解决它,所以他们只是采取了一条简单的路线.