对于通用接口(interface):
public interface Foo<T> {
void f(T t);
}
两个字段的区别:
public class Bar {
Foo foo1;
Foo<?> foo2;
}
是foo2
吗是一个通用类型并且 foo
不是。自 ?
是一个通配符(我认为这意味着任何类型)并且每种类型都是 Object 的子类型,那么我希望 Foo<?>
和 Foo<Object>
在语义和句法上等价。
但是,请检查以下内容:
public class Puzzler {
void f() {
Integer i = null;
Foo<?> foo1 = null;
foo1.foo(i); // ERROR
Foo foo2 = null;
foo2.foo(i); // OKAY
Foo<Integer> foo3 = null;
foo3.foo(i); // OKAY
Foo<Object> foo4 = null;
foo4.foo(i); // OKAY
}
private interface Foo<T> {
void foo(T t);
}
}
所以 Foo<?>
和 Foo<Object>
在句法上不相同。
这是怎么回事?我很难理解这一点。
最佳答案
Foo<?>
在语义上与 Foo<? extends Object>
相同: 这是一个 Foo
带有特定类型的参数,但关于“某物”的唯一已知信息是它是 Object
的某个子类(这并没有说太多,因为所有类都是 Object
的子类)。 Foo<Object>
,另一方面,是一个 Foo
特别是类型参数 Object
.虽然一切都与 Object
分配兼容, 并非所有内容都与 ?
兼容其中 ?
延伸Object
.
这是一个为什么 Foo<?>
的例子应该产生一个错误:
public class StringFoo implements Foo<String> {
void foo(String t) { . . . }
}
现在将您的示例更改为:
Foo<?> foo1 = new StringFoo();
自 i
是一个 Integer
, 编译器不可能允许 foo1.foo(i)
编译。
注意
Foo<Object> foo4 = new StringFoo();
也不会根据 matching parameterized types 的规则进行编译自 Object
和 String
是可证明的不同类型。
Foo
(根本没有类型参数——原始类型)通常应被视为编程错误。根据Java Language Specification (§4.8) ,但是,编译器接受此类代码是为了不破坏非通用的遗留代码。
因为type erasure ,这对生成字节码没有任何影响。也就是说,它们之间的唯一区别在于编译时。
关于java - Java 的类型参数通配符到底是什么意思? Foo 和 Foo<?> 之间的真正区别是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9594753/