静态值中的泛型和通配符。它说是相同的 class 但不编译
Generics and wildcards in static values. It says that is the same class but doesnt compile
public interface Moo<T> {
T getValue();
}
public class Bar<T> {
}
public class Foo<T extends Moo<Long>> {
private static Foo<?> foo;
private Bar<T> bar;
public Foo(Bar<T> bar) {
this.bar = bar;
}
//getters and setters
public void barfoo(List<T> list) {
System.out.println(list);
}
public void foobar(T t) {
System.out.println(t.getValue());
}
public void other() {
List<? extends Moo<Long>> somelist = null;
foo.barfoo(somelist);
}
}
它生成错误,说我无法编译,因为 somelist
无法进入该函数。说 "Required ? extends Moo found ? extends Moo"
我不知道为什么会这样,也不知道怎么解决。
您的 class Foo
的任何实例都将使用扩展 Moo<Long>
的具体类型 T
创建。方法 barfoo
需要类型为 List<T>
的参数,其中此 T
与实例化的类型完全相同。
现在你用List<? extends Moo<Long>>
调用这个方法。那个 ? extends Moo<Long>
和你的类型 T
不一样。它可以是 Moo<Long>
的任何其他子类型。所以编译器必须拒绝这个方法调用。
为了清楚起见,让我们创建一个 Moo
接口的实现:
public class MooImpl implements Moo<Long> {
@Override
public Long getValue() {
return null;
}
}
回到你的 class,在编译器的眼中,类型 Foo
的 static
成员有一个 unknown 泛型parameter,意思是在Runtime,这个参数可以用anything代替。我们可以很容易地用 Foo
实例实例化 static
成员,由 MooImpl
参数化(我们被允许这样做,因为 MooImpl extends Moo<Long>
。我们说 MooImpl
是 编译时 Moo<Long>
的已知子类型。
现在让我们看一下other()
方法。在运行时,? extends Moo<Long>
可能会导致与 T
不同的类型,这就是编译器会报错的原因。之所以这样做,是因为 ? extends Moo<Long>
代表 Moo<Long>
的 未知子类型 。这样它 不同于 与 已知子类型 (MooImpl
).
为了让它生效,我们可以把barfoo()
方法的参数改成List<? extends Moo<Long>>
.
public class Foo<T extends Moo<Long>> {
private static Foo<?> foo = new Foo<MooImpl>(new Bar<MooImpl>());
private Bar<T> bar;
public Foo(Bar<T> bar) {
this.bar = bar;
}
public void barfoo(List<? extends Moo<Long>> list) {
System.out.println(list);
}
public void foobar(T t) {
System.out.println(t.getValue());
}
public void other() {
List<? extends Moo<Long>> somelist = null;
foo.barfoo(somelist);
}
}
public interface Moo<T> {
T getValue();
}
public class Bar<T> {
}
public class Foo<T extends Moo<Long>> {
private static Foo<?> foo;
private Bar<T> bar;
public Foo(Bar<T> bar) {
this.bar = bar;
}
//getters and setters
public void barfoo(List<T> list) {
System.out.println(list);
}
public void foobar(T t) {
System.out.println(t.getValue());
}
public void other() {
List<? extends Moo<Long>> somelist = null;
foo.barfoo(somelist);
}
}
它生成错误,说我无法编译,因为 somelist
无法进入该函数。说 "Required ? extends Moo
您的 class Foo
的任何实例都将使用扩展 Moo<Long>
的具体类型 T
创建。方法 barfoo
需要类型为 List<T>
的参数,其中此 T
与实例化的类型完全相同。
现在你用List<? extends Moo<Long>>
调用这个方法。那个 ? extends Moo<Long>
和你的类型 T
不一样。它可以是 Moo<Long>
的任何其他子类型。所以编译器必须拒绝这个方法调用。
为了清楚起见,让我们创建一个 Moo
接口的实现:
public class MooImpl implements Moo<Long> {
@Override
public Long getValue() {
return null;
}
}
回到你的 class,在编译器的眼中,类型 Foo
的 static
成员有一个 unknown 泛型parameter,意思是在Runtime,这个参数可以用anything代替。我们可以很容易地用 Foo
实例实例化 static
成员,由 MooImpl
参数化(我们被允许这样做,因为 MooImpl extends Moo<Long>
。我们说 MooImpl
是 编译时 Moo<Long>
的已知子类型。
现在让我们看一下other()
方法。在运行时,? extends Moo<Long>
可能会导致与 T
不同的类型,这就是编译器会报错的原因。之所以这样做,是因为 ? extends Moo<Long>
代表 Moo<Long>
的 未知子类型 。这样它 不同于 与 已知子类型 (MooImpl
).
为了让它生效,我们可以把barfoo()
方法的参数改成List<? extends Moo<Long>>
.
public class Foo<T extends Moo<Long>> {
private static Foo<?> foo = new Foo<MooImpl>(new Bar<MooImpl>());
private Bar<T> bar;
public Foo(Bar<T> bar) {
this.bar = bar;
}
public void barfoo(List<? extends Moo<Long>> list) {
System.out.println(list);
}
public void foobar(T t) {
System.out.println(t.getValue());
}
public void other() {
List<? extends Moo<Long>> somelist = null;
foo.barfoo(somelist);
}
}