Недавно я начал изучать дженерики в Java, и я понимаю основные концепции дженериков. Однако я не понимаю одного: я не знаю, почему следующий метод не работает:
public class Generics<T extends Number> {
T num;
Generics(T n){
num = n;
}
//...
T timesTwo() { //Return the value that's twice as much as 'num'
return num * 2;
}
}
Это был мой первый подход, и я как бы понимаю, почему он не работает. В сообщении об ошибке сказано: Оператор * не определен для типов аргументов T, int.
Я предполагаю, что Java не могла умножить типы T и int вместе. (Но не должен ли компилятор иметь возможность автоматически распаковывать T, поскольку он участвует в выражении И класс расширяет Number?)
Поэтому я отказался от этого метода и попытался заменить его этим методом:
T times(T i) { //This method was supposed to receive another T object as
//an argument and multiply them together, then return the output
return num * i;
}
Но снова появилось то же самое сообщение об ошибке (единственное изменение заключалось в том, что int был заменен на T).
Почему код не работает и как это исправить?
* не определен для Number. Он определен для числовых примитивов (int, long, double и т. д.), К которым классы оболочки (Integer, Long, Double и т. д.) Имеют неявное преобразование. Тот факт, что все классы-оболочки расширяют Number, не означает, что вы можете использовать * на Number.
Проблема заключается в умножении общего, посмотрите stackoverflow.com/questions/27107043/…




Я согласен с первыми двумя комментариями. Кроме того, это не общая проблема, просто метод не работает, потому что он не должен работать, потому что предположение о боксе, которое вы сделали, здесь не применимо.
Автобоксирование и распаковка предусмотрены для некоторых числовых типов, но не для всех. См. Таблицу ниже: https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
Итак, пока это работает так, как вы ожидаете (потому что оба типа находятся в поддерживаемой таблице):
public static void main(String[] args) {
Integer a = 3;
Integer b = 2;
Number answer = a * b;
System.out.println("Answer: " + answer);
}
Этот интуитивно эквивалентный код НЕ будет работать:
public static void main(String[] args) {
Number a = 3;
Number b = 2;
Number answer = a * b;
System.out.println("Answer: " + answer);
}
Фактически, с точки зрения компилятора, он дает вам такой же косоглазый взгляд, как если бы вы попробовали это:
public static void main(String[] args) {
String a = "what does it even mean to multiply a string with a number..??";
Byte b = 2;
Number answer = a * b;
System.out.println("Answer: " + answer);
}
Итак, чтобы закончить точку, с точки зрения компилятора, поскольку автоматическая упаковка не применяется, он так же запутан, как умножение двух чисел, так и как умножение двух других случайных объектов, таких как String и Byte, и сообщает об ошибке. соответственно