Java类定义的类型推断失败。我该如何解决?

时间:2019-04-23 12:46:12

标签: java kotlin abstract-class covariance

在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>

为什么这不起作用,我应该如何解决?

1 个答案:

答案 0 :(得分:1)

以下是有效的Kotlin代码(假设DogAnimal的子类):

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>,并且ClassT中不是协变的。为了编译该代码,您可以执行以下操作:

fun doSomethingWithType(type: Class<out Message>) { ... }
doSomethingWithType(Int32::class.java)

只要您仅从T中抽出Class<T>,即Class仅产生类型T,这将起作用。