Java 通配符默认为 java.lang.Object 而不是上限
Java wildcards defaulted to java.lang.Object instead of upper bound
给定代码
abstract class Base<Thistype extends Base>
{
public void addOnSomethingListener(Consumer<? super Thistype> action)
{}
public void foo()
{
System.out.println("foo");
}
}
class Simple<Thistype extends Simple> extends Base<Thistype>
{
}
class Test1 extends Simple<Test1>
{
}
class Test2 extends Simple
{
}
class Test
{
public static void main(String[] args)
{
Test1 test1 = new Test1();
Test2 test2 = new Test2();
test1.addOnSomethingListener(test ->
{
test.foo(); // VALID as "test" is of type "Thistype" which is "Test1".
});
test2.addOnSomethingListener(test ->
{
test.foo(); // INVALID as "test" is of type "Thistype" which is "java.lang.Object" instead of "Base" which is the upper bound.
});
}
}
为什么classTest2
的泛型类型不是默认为classBase
而是默认为classjava.lang.Object
?
我提供了上限,但如果使用通配符或根本没有给出泛型,这似乎无关紧要。
main函数里面的代码你问我应该可以编译吧
通过声明 Test2
class 而不指定其类型参数:
class Test2 extends Simple {}
您正在创建 raw type。因此编译器将其视为 Object
.
的实例
它没有"default to Object
"。
实际发生的事情是,通过使用原始类型(Test2
扩展原始类型 Simple
),它 "turns off" 该类型的所有泛型。所以 Test2
的 addOnSomethingListener
方法(从原始类型 Simple
继承)实际上具有签名 void addOnSomethingListener(Consumer action)
(即参数的类型被擦除为原始类型 Consumer
).
碰巧原始类型 Consumer
的 accept
方法具有签名 void accept(Object)
(因为它通常是 void accept(T)
,但 T
in Consumer
是无界的,因此当使用原始类型 Consumer
时,它会被擦除为 void accept(Object)
.
给定代码
abstract class Base<Thistype extends Base>
{
public void addOnSomethingListener(Consumer<? super Thistype> action)
{}
public void foo()
{
System.out.println("foo");
}
}
class Simple<Thistype extends Simple> extends Base<Thistype>
{
}
class Test1 extends Simple<Test1>
{
}
class Test2 extends Simple
{
}
class Test
{
public static void main(String[] args)
{
Test1 test1 = new Test1();
Test2 test2 = new Test2();
test1.addOnSomethingListener(test ->
{
test.foo(); // VALID as "test" is of type "Thistype" which is "Test1".
});
test2.addOnSomethingListener(test ->
{
test.foo(); // INVALID as "test" is of type "Thistype" which is "java.lang.Object" instead of "Base" which is the upper bound.
});
}
}
为什么classTest2
的泛型类型不是默认为classBase
而是默认为classjava.lang.Object
?
我提供了上限,但如果使用通配符或根本没有给出泛型,这似乎无关紧要。
main函数里面的代码你问我应该可以编译吧
通过声明 Test2
class 而不指定其类型参数:
class Test2 extends Simple {}
您正在创建 raw type。因此编译器将其视为 Object
.
它没有"default to Object
"。
实际发生的事情是,通过使用原始类型(Test2
扩展原始类型 Simple
),它 "turns off" 该类型的所有泛型。所以 Test2
的 addOnSomethingListener
方法(从原始类型 Simple
继承)实际上具有签名 void addOnSomethingListener(Consumer action)
(即参数的类型被擦除为原始类型 Consumer
).
碰巧原始类型 Consumer
的 accept
方法具有签名 void accept(Object)
(因为它通常是 void accept(T)
,但 T
in Consumer
是无界的,因此当使用原始类型 Consumer
时,它会被擦除为 void accept(Object)
.