为什么一处的原始类型会导致其他地方的通用调用点被视为原始类型?
考虑这个例子:
import java.util.*;
class Foo<T> {
public int baz(List<String> stringlist) { return 1; }
public int baz(ArrayList<Object> objectlist) { return 2; }
public static void main(String[] args) {
Foo<String> foo = new Foo<String>(); // (A)
//Foo foo = new Foo(); // (B)
System.out.println(foo.baz(new ArrayList<String>()));
}
}
为什么它在 (A)
中打印 1
,而在 (B)
中打印 2
?
我知道方法解析是如何工作的,所以不需要向我解释。
我想知道这个“功能”背后更深层的动机。 为什么没有关于它的删除警告? (只有一个关于Foo foo = new Foo()
。)
尽管给出了泛型类型,为什么方法解析使用擦除语义?
Consider this example:
import java.util.*;
class Foo<T> {
public int baz(List<String> stringlist) { return 1; }
public int baz(ArrayList<Object> objectlist) { return 2; }
public static void main(String[] args) {
Foo<String> foo = new Foo<String>(); // (A)
//Foo foo = new Foo(); // (B)
System.out.println(foo.baz(new ArrayList<String>()));
}
}
Why does it print 1
in (A)
, but 2
with (B)
?
I know how method resolution works, so no need to explain that to me.
I want to know the deeper motivation behind this "feature".
Why is there no erasure warning about it? (There is just one about Foo foo = new Foo()
.)
Why does method resolution use erased semantics although the generic type is given?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是因为当编译器解决重载时,它会将每个方法视为通用方法或非泛型,绝不是两者的混合,因此候选者是:
Foo.baz(List)
Foo.baz(ArrayList
如果
foo
是Foo
,或Foo.baz(List)
Foo.baz(ArrayList )
如果
foo
是Foo
。不存在
Foo.baz(List)
这样的东西。要么考虑所有类型参数,要么不考虑。 (我不知道 JLS 中明确指出了这一点,但这是有道理的,因为将泛型方法视为原始等效方法是一种向后兼容性功能。)在第一种情况下,
Foo.baz(List)
匹配,但Foo.baz(ArrayList
在第二种情况下,两个函数都匹配,并且
Foo.baz(ArrayList)
是 更具体,所以选择了。It's because when the compiler is resolving overloads, it considers each method as either generic or non-generic, never a mixture of the two, so the candidates are:
Foo<T>.baz(List<String>)
Foo<T>.baz(ArrayList<Object>)
if
foo
is aFoo<String>
, orFoo.baz(List)
Foo.baz(ArrayList)
if
foo
is aFoo
.There is no such thing as
Foo.baz(List<String>)
. Either all type parameters are considered or none are. (I am not aware of this being explicitly stated in the JLS, but it makes sense since treating a generic method as if it were the raw equivalent is a backwards-compatibility feature.)In the first case,
Foo<T>.baz(List<String>)
matches butFoo<T>.baz(ArrayList<Object>)
does not.In the second case both functions match, and
Foo.baz(ArrayList)
is more specific, so it is chosen.如果只保留单个方法 baz(ArrayList
奇怪的是它确实在情况 (B) 中编译,但他们一定采取了一些奇怪的决定来保持与非泛型集合的向后兼容性。
It won't even compile case (A) if you only keep the single method
baz(ArrayList<Object>)
(error: method cannot be applied to given type).I guess
ArrayList<String>
is not a subclass ofArrayList<Object>
.It's weird that it does compile in case (B), but they must have taken some weird decisions to kept backward compatibility with non-generic collections.