我正在寻找Kotlin中有关Java泛型的文档或规范。
我对父类和子类之间的不同行为很好奇。
// A.java
public class A<T> {
public T value;
public A(T value) {
this.value = value;
}
}
// B.java
public class B<T> extends A<T> {
public B(T value) {
super(value);
}
}
从Kotlin中使用上面的Java代码。
fun main() {
val a = A<String>("a")
val b = B<String>("b")
val aValue = getValue(a)
val bValue = getValue(b)
// lint error: Condition 'aValue == null' is always 'false'
// aValue is non-null type
println(aValue == null)
// No lint error
// bValue is platform type(String!)
println(bValue == null)
}
fun <T> getValue(a: A<T>): T {
return a.value
}
在这种情况下,对于超类,函数的结果被标记为非空。
另一方面,对于子类,函数的结果被标记为平台类型。
有人知道这个规范吗?
如果你能告诉我有关官方文件等,那就太有帮助了。
编译器可以判断出aValue == null
总是假的,因为aValue
的类型是A<String>
,经过类型推断,getValue
的类型参数T
推断为不可空的String
。注意,这里的T
不能是String?
,因为A<String>
不是A<String?>
的子类型,就像List<Dog>
不是List<Animal>
一样。因此,String
是getValue
对aValue
的返回值。
另一方面,bValue
类型为B<String>
。关于类型参数T
,类型推断说了什么?T
可以是String
或者String?
。B<T>
可以继承A<T>
,T
是非空的,但B<T>
也可以继承A<T?>
,不是吗?Java代码中没有注释说明这一点。因此,Kotlin编译器选择谨慎,将T
推断为String?
,假定B<T>
继承自A<T?>
。
如果您的意思是B<T>
继承自A<T>
,请在Java代码中用Kotlin能够识别的注释之一标记:
class B<T> extends A<@NotNull T> {
如果您无法控制Java代码,您还可以显式指定类型参数:
val bValue = getValue<String>(b)
由于平台类型是特定于平台的,它们不在Kotlin/Core规范中。这种特定的行为可能会出现在尚未发布的Kotlin/JVM规范中:(