java.lang.Number не реализует "+" или любые другие операторы? - PullRequest
7 голосов
/ 22 января 2012

Я создаю класс, который должен использоваться с массивом чисел любого типа (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» не реализует операторы «+ =» или «/ =».Хуже того, класс Number Java не реализует даже самые простые операторы, такие как «+» или «-»!Как я могу создать метод, который возвращает среднее значение массива чисел, если java не позволит мне скомпилировать его, потому что он думает, что числа не могут быть добавлены?!?!

Ответы [ 7 ]

9 голосов
/ 22 января 2012

Вы неправильно понимаете, как числа работают в 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 должна точно знать , с каким типом номера он имеет дело для выполнения бокс / распаковка.

1 голос
/ 22 января 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;  
}
1 голос
/ 22 января 2012

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

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

0 голосов
/ 15 июня 2018
public int showAllNum(Number i, Number j) {
    return (int) (i.doubleValue()+j.doubleValue()); 
}
0 голосов
/ 22 января 2012

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

0 голосов
/ 22 января 2012

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

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

0 голосов
/ 22 января 2012

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

...