java.lang.Number не реализует + или другие операторы?

Я создаю класс, который, как предполагается, можно использовать с массивом любого типа числа (float, int и т. Д.), Поэтому вот один метод, который у меня есть:

// T extends Number
public synchronized T[] average() {
    Number[] ret = new Number[queue[0].length];
    for (int i = 0; i < ret.length; ++i) {
        for (int j = 0; j < size; ++j) {
            ret[i] += queue[j][i]; // WTF ERROR?!
        }
        ret[i] /= size; // WTF ERROR?!
    }
    return (T[])ret;
}

За исключением того, что это не будет компилироваться, потому что "Number" не реализует операторы "+ =" или "/ =". Хуже того, класс Java Number не реализует даже самые простые операторы, такие как «+» или «-»! Как я могу создать метод, который возвращает среднее значение массива чисел, если java не позволяет мне его скомпилировать, потому что считает, что числа нельзя складывать?!?!


person Dasmowenator    schedule 22.01.2012    source источник
comment
В Java нет таких операторов перегрузки, как C ++. Что у него есть, так это методы. Например, java.lang.BigInteger имеет метод add.   -  person Paul Tomblin    schedule 22.01.2012
comment
Добро пожаловать в Java, где операторы не являются функциями. Кроме того, вам следует узнать больше об стирании типа, поскольку обобщенные типы в Java работает совсем не так, как шаблоны в C ++.   -  person Ted Hopp    schedule 22.01.2012
comment
Кстати, Number абстрактное. Вы даже не сможете его создать.   -  person Paul Tomblin    schedule 22.01.2012
comment
Ничто не реализует операторов; это языковые / синтаксические конструкции. Строки имеют особый регистр с синтаксическим сахаром.   -  person Dave Newton    schedule 22.01.2012
comment
@PaulTomblin с единственным исключением +, который может объединять строки   -  person Thorbjørn Ravn Andersen    schedule 22.01.2012
comment
Еще одна проблема, на которую никто не указал, - это последняя строчка. Если переменная является экземпляром X, вы не можете привести ее к подклассу X.   -  person Mike Baranczak    schedule 22.01.2012


Ответы (7)


Вы неправильно понимаете, как числа работают в Java. Класс Number - это суперкласс числовых классов-оболочек (Integer, Float и т. Д.), Полезный для представления примитивных типов (int, float и т. Д.) Как объектов, но он не работает с обычной арифметикой. операторы.

Если вы собираетесь использовать арифметические операторы, используйте примитивные типы. Если вам нужно создать «общий» метод, который работает для всех числовых типов данных, у вас нет другого выбора, кроме как создать несколько перегруженных версий одного и того же метода, по одной для каждого типа данных, например:

public  float[] average(float[][]  queue) {...}
public double[] average(double[][] queue) {...}

Также имейте в виду, что такой код выглядит для работы с типами оболочек:

Integer i = 0;
i += 1;
System.out.println(i);

... Но под капотом Java автоматически упаковка и распаковка Integer, поскольку оператор += работает только для примитивных типов. Это работает, потому что мы явно указываем, что это число Integer, но это не сработает для Number, поскольку Java должна точно знать с каким типом числа имеет дело для выполнения упаковки / распаковка.

person Óscar López    schedule 22.01.2012
comment
В дополнение к тому, что Number API не работает с арифметическими операторами, он не предоставляет никаких методов для выполнения арифметических операций. - person Stephen C; 22.01.2012

Вам нужно преобразовать свои числа в примитивные типы, и тогда арифметические операторы будут работать. Вы заметите, что у Number есть doubleValue, intValue и т. Д. ...

или, в качестве альтернативы, вы можете преобразовать в BigDecimal и использовать арифметические методы, определенные в этом классе (не _5 _, _ 6_ и т. д., но add, multiply и т. д. ...). Этот метод будет более точным (если вам нужна максимальная точность, используйте BigDecimal), поскольку числа с плавающей запятой и двойные числа представляют только дискретный набор числовых значений. Имейте в виду, что BigDecimals неизменяемы, поэтому вам всегда нужно присвоить результат операции ссылке.

person hvgotcodes    schedule 22.01.2012
comment
Если он собирается явно преобразовать в double, int и т. Д., То почему, черт возьми, он для начала использует Number? Я не думаю, что это решение. - person Andres F.; 22.01.2012

Я думаю это то что ты хочешь

public synchronized average() {  
    double ret = new double[queue[0].length];  
    for (int i = 0; i < ret.length; ++i) {  
        for (int j = 0; j < size; ++j) {  
            ret[i] += queue[j][i];  
        }  
        ret[i] /= size;  
    }  
    return ret;  
}
person Victor Grazi    schedule 22.01.2012

К сожалению, вы не можете. Арифметические операторы работают только с примитивными типами (и благодаря автобоксу и автооткрытию их оболочек). Вы должны переопределить данный метод для всех примитивных типов, над которыми вам нужен метод для работы, как это делается во многих классах JDK.

person Natix    schedule 22.01.2012

В Java арифметические операторы работают только с примитивными типами. Проблема здесь в том, что в Java есть представления классов этих примитивных типов, и переключение с одного на другое обычно неявно с помощью функции, известной как autoboxing.

В этом случае вам нужно будет реализовать методы для необходимых вам типов арифметических операций, возможно, придется создать перегруженные методы для всех возможных числовых типов, передаваемых для каждой операции.

person Community    schedule 22.01.2012

Поскольку все возможные byte, short, char, int, float, double могут быть представлены как double, это намного эффективнее (поскольку это примитив вместо любого объекта) и проще использовать double вместо Number. Если вы нужно long точно или BigDecimal или BigInteger.

person Peter Lawrey    schedule 22.01.2012
comment
@KennethNoland Можете ли вы привести пример значения этих типов, которое нельзя сохранить в double без потери точности? double имеет как минимум 53 бита точности, что более чем достаточно для хранения любого из этих типов. - person Peter Lawrey; 03.06.2013

person    schedule
comment
Вы должны правильно отформатировать это и объяснить свой ответ. - person Michael; 15.06.2018