mws*_*ltn 8 java generics types java-ee
对于通用接口:
public interface Foo<T> {
void f(T t);
}
Run Code Online (Sandbox Code Playgroud)
两个字段之间的区别:
public class Bar {
Foo foo1;
Foo<?> foo2;
}
Run Code Online (Sandbox Code Playgroud)
这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);
}
}
Run Code Online (Sandbox Code Playgroud)
所以,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) { . . . }
}
Run Code Online (Sandbox Code Playgroud)
现在将您的示例更改为:
Foo<?> foo1 = new StringFoo();
Run Code Online (Sandbox Code Playgroud)
既然i是Integer,那么编译器就没有办法允许foo1.foo(i)编译.
注意
Foo<Object> foo4 = new StringFoo();
Run Code Online (Sandbox Code Playgroud)
也不会根据该规则编译匹配参数化类型,因为Object和String都是可证明不同的类型.
Foo(通常没有类型参数 - 原始类型)通常应被视为编程错误.但是,根据Java语言规范(第4.8节),编译器接受此类代码以便不破坏非泛型的遗留代码.
由于类型擦除,这些都不会产生字节代码.也就是说,它们之间的唯一区别是在编译时.