Java и дженерики.Разве 0 не число? - PullRequest
8 голосов
/ 26 июля 2011

Чего мне не хватает в этом фрагменте кода?

public class Zero<N extends Number> {
  public N zero() {
    return new Integer(0);
  }
}

В нем говорится:

Несоответствие типов: невозможно преобразовать целое число в N

Спасибо!

Обновление Я изменил фрагмент, чтобы использовать целое число.То же самое происходитИ это происходит даже при создании анонимного подкласса Number.Может ли это быть Затмение, которое ошибочно по этому поводу?

Ответы [ 5 ]

13 голосов
/ 26 июля 2011

Хотя целое число является числом, оно может быть несовместимо с N, который может быть любым подклассом числа.

12 голосов
/ 26 июля 2011

Integer не обязательно является суперклассом N, поэтому нельзя просто установить значение Integer для объекта типа N.

Подумайте об этом так: если кто-то создает Zero<N> какZero<Double>, класс фактически становится:

public class Zero {
  public Double zero() {
    return new Integer(0);
  }
}

, что явно недопустимо.

Кроме того, вы также не можете сделать return 0, потому что таким же образом, естьу компилятора нет способа узнать, как преобразовать его в N. (Компилятор может только автозапускать те типы, о которых он знает, но с помощью обобщений вы расширили доступные типы, добавив в них также собственные реализации Number.)

2 голосов
/ 26 июля 2011

Проблема с вашим кодом заключается в том, что Java должна быть в состоянии подтвердить, что возвращаемый тип функции должен быть конвертируемым в N extends Number для любого N.Так, в частности, если бы я создал экземпляр класса с Double, как в

Zero<Double> z = new Zero<Double>();
z.zero();

Вы столкнулись бы с проблемой, потому что zero говорит, что он возвращает Double, но этона самом деле возвращает Integer.Ошибка типа указывает на то, что компилятор обеспокоен тем, что что-то подобное произойдет.

Насколько я знаю, в Java нет хорошего способа сделать это, потому что обобщения применяются через стирание;он не может знать тип аргумента.

1 голос
/ 26 июля 2011

Когда «N» расширяет «Number», «N» становится специализацией «Number», и вы не можете назначить экземпляр базового класса ссылочной переменной его специализации (проблема upcast).Это верно и при возвращении.Экземпляр базового класса не может быть возвращен с использованием типа специализации.

1 голос
/ 26 июля 2011

0 - это int, но поскольку ваш метод возвращает объект, он будет автоматически помещен в Integer.Проблема заключается в том, что возвращение Integer, где любой подкласс числа разрешен, не разрешено компилятором.Это просто потому, что вы можете создать экземпляр своего класса как

new Zero<Double>()

, и в этом случае возврат Integer не будет совместим с ожидаемым типом возврата: Double.

...