在 Kotlin 中,我发现,与 Java 相比,可以使用协方差完成以下操作:
ArrayList<Dog> listOfDogs = listOf(dog1, dog2)
ArrayList<Animal> animalList = listOfDogs // No compiler error
在我的情况下,我有一个接口消息:
public interface Message {
RawMessage toRawMessage();
}
例如,我有一条Int32
消息:
public interface Int32 extends Message {
// abstract methods
}
现在我有一个参数type
类型为 Class<Message>
的方法:
fun doSomethingWithType(type: Class<Message>) {
// Implementation
}
问题是我正在尝试传递一个从消息扩展的 Java 类,例如:
doSomethingWithType(Int32::class.java)
但这给了我以下编译器错误:
Expected type mismatch:
required: Class<Message>
found: Class<Int32>
为什么这不起作用,我应该如何解决?
以下是有效的 Kotlin 代码(假设 Dog
是 Animal
的子类(:
val listOfDogs: List<Dog> = listOf(dog1, dog2)
val listOfAnimals: List<Animal> = listOfDogs
这背后的原因是List
是一个 Kotlin 接口,定义为:
public interface List<out E> : Collection<E>
不幸的是,你不能在纯Java中做同样的事情,但你可以这样做:
List<Dog> listOfDogs = new ArrayList<>();
List<? extends Animal> listOfAnimals = listOfDogs;
现在,doSomethingWithType
期望在您提供Class<Int32>
时出现Class<Message>
,并且Class
在T
中不是协变的。为了使该代码编译,您可以执行以下操作:
fun doSomethingWithType(type: Class<out Message>) { ... }
doSomethingWithType(Int32::class.java)
只要您只从Class<T>
中提取T
,这将起作用,即 Class
只会产生 T
型。