Общее назначение типа говорит о несовместимом типе для более ограничительного назначения

112
14

У меня есть переменная следующего типа


Pair<String, Class<?>> test;

Я пытаюсь создать его так:


Class<? extends Animal> animal = Tiger.class;
test = Pair.create("tiger", animal);

Код дает мне "Несовместимые типы" (при создании пары с животными). Хотя определение переменных тестов позволяет классу любого типа и животного определять границу любого дочернего класса животного, который является более строгим, чем исходный. Так не должно ли это задание работать?

спросил(а) 2021-01-19T17:24:14+03:00 9 месяцев назад
1
Решение
103

Tiger является подтипом Animal, но Class<Tiger> не является подтипом Class<Animal>. Родитель как Class<Tiger>, так и Class<Animal> равен Class<?>.


Аналогично, Pair<String, Class<? extends Animal>> не является подтипом Pair<String, Class<?>>, они представляют собой различные объекты, даже если Class<? extends Animal>> является подтипом Class<?>.


Чтобы было легче понять, подумайте об этом с точки зрения коллекций: если вы получили Pair<String, List<?>>, и вы назначили ему Pair<String, List<? extends Number>>; вы могли бы затем добавить в список String. http://ideone.com/dcXnWs

В Java8 работает код http://ideone.com/AkK7Zv; честно говоря, я не уверен, что компилятор делает дополнительно (все равно придется разбираться в новых функциях). В любом случае, поскольку вы можете видеть, что ошибка компилятора для следующих образцов достаточно объяснительна:


ответил(а) 2021-01-19T17:24:14+03:00 9 месяцев назад
92

Возможное объяснение, почему он работает в Java 8 (который улучшил вывод типа):


public static class Pair<A, B> {
public static <A, B> Pair<A, B> create(A a, B b) {
return new Pair<A, B>();
}
}

public static class Animal {}
public static class Tiger extends Animal {}

public static final void main(final String[] args) {
Class<? extends Animal> animal = Tiger.class;
Pair<String, Class<?>> test = Pair.create("tiger", animal);
}


В соответствии с Правилами подтипирования Java Generics:


    Верно, что: Class<? extends Animal> extends Class<?>
    Неверно, что: Pair<String, Class<? extends Animal>> extends Pair<String, Class<?>>

Из-за 2. он не работает в Java 7, но Java 8 использует 1.:


Pair<String, Class<?>> test = Pair.create("tiger", animal);

Java 8 делает вывод, что аргумент a имеет тип String, а аргумент b имеет тип Class<?>. Поскольку 1. истинно, он может передать второй аргумент Class<?>, который затем подходит к типу переменной test.


Поэтому, поскольку он может передать единственный аргумент перед передачей его методу, ему не нужно выводить возвращаемый результат (что невозможно).

ответил(а) 2021-01-19T17:24:14+03:00 9 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема