在Kotlin中,我发现与Java相比,可以使用covariance完成以下操作:
ArrayList<Dog> listOfDogs = listOf(dog1, dog2)
ArrayList<Animal> animalList = listOfDogs // No compiler error
在我的情况下,我有一个接口Message:
public interface Message {
RawMessage toRawMessage();
}
例如,我有一条Int32
消息:
public interface Int32 extends Message {
// abstract methods
}
现在,我有一个方法,类型为type
的参数Class<Message>
:
fun doSomethingWithType(type: Class<Message>) {
// Implementation
}
问题是我正在尝试传递从Message扩展的Java类,例如:
doSomethingWithType(Int32::class.java)
但这给了我以下编译器错误:
Expected type mismatch:
required: Class<Message>
found: Class<Int32>
为什么这不起作用,我应该如何解决?
答案 0 :(得分:1)
以下是有效的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<Message>
时期望Class<Int32>
,并且Class
在T
中不是协变的。为了编译该代码,您可以执行以下操作:
fun doSomethingWithType(type: Class<out Message>) { ... }
doSomethingWithType(Int32::class.java)
只要您仅从T
中抽出Class<T>
,即Class
仅产生类型T
,这将起作用。