Изменение значения в объекте Generics в Java

Недавно я начал изучать дженерики в 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).

Почему код не работает и как это исправить?

«Но не должен ли компилятор иметь возможность автоматически распаковывать T, поскольку он участвует в выражении И класс расширяет Number?)» ... почему ты так думаешь? Не каждый подкласс Number является оболочкой примитивного типа.
Tom 08.04.2021 06:11
* не определен для Number. Он определен для числовых примитивов (int, long, double и т. д.), К которым классы оболочки (Integer, Long, Double и т. д.) Имеют неявное преобразование. Тот факт, что все классы-оболочки расширяют Number, не означает, что вы можете использовать * на Number.
Sweeper 08.04.2021 06:15

Проблема заключается в умножении общего, посмотрите stackoverflow.com/questions/27107043/…

Lia 08.04.2021 06:40
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
3
30
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я согласен с первыми двумя комментариями. Кроме того, это не общая проблема, просто метод не работает, потому что он не должен работать, потому что предположение о боксе, которое вы сделали, здесь не применимо.

Автобоксирование и распаковка предусмотрены для некоторых числовых типов, но не для всех. См. Таблицу ниже: 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, и сообщает об ошибке. соответственно

Другие вопросы по теме