Ошибка определения типа для определения класса Java. Как я могу решить это? - PullRequest
1 голос
/ 23 апреля 2019

В Kotlin я обнаружил, что, в отличие от Java, с помощью covariance можно сделать следующее:

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-класс, расширяющийся из Message, например:

doSomethingWithType(Int32::class.java)

Но это дает мне следующую ошибку компилятора:

Expected type mismatch: 
required: Class<Message> 
found:    Class<Int32>

Почему это не работаети как мне это решить?

1 Ответ

1 голос
/ 23 апреля 2019

Ниже приведен действительный код 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.

...