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不允许我编译它,我怎么能创建一个返回Numbers数组平均值的方法,因为它认为数字不能被添加?!?!

你误解了数字在Java中的工作方式。 Number类是数字包装类( IntegerFloat等)的超类,可用于将基本类型( intfloat等)表示为对象,但它不适用于通常的算术运算符。

如果您打算使用算术运算符,则使用原始类型。 如果需要构建适用于所有数值数据类型的“通用”方法,则别无选择,只能构建同一方法的多个重载版本,每种数据类型对应一个,例如:

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

还要注意这样的代码似乎适用于包装类型:

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

…但在引擎盖下,Java会自动装箱并取消装箱 Integer ,因为+=运算符仅适用于基本类型。 它的工作原理是因为我们明确指出该数字是一个Integer ,但它不适用于一个Number ,因为Java需要确切地知道它正在处理什么类型的数字来执行装箱/拆箱。

您需要将数字转换为基本类型,然后算术运算符将起作用。 您会注意到Number确实有doubleValueintValue等….

或者,你可以转换为BigDecimal ,并使用在该类上定义的算术方法(不是+-等,但是addmultiply等等)。 此方法将更准确(如果您需要最佳精度,请使用BigDecimal ),因为浮点数和双精度数仅表示一组离散的数值。 请记住,BigDecimals是不可变的,因此您始终需要将操作的结果分配给引用。

我想这就是你想要的

 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; } 

可悲的是,你做不到。 算术运算符仅适用于基本类型(并且由于它们的包装器上的自动装箱和自动装箱)。 您必须为需要该方法处理的所有基本类型覆盖给定方法,就像在许多JDK类中一样。

在Java中,算术运算符仅适用于基本类型。 这里的问题是Java具有这些原始类型的类表示,并且通过称为自动装箱的特征,从一个到另一个的切换通常是隐含的。

在这种情况下,您需要为所需的算术运算类型实现方法,可能必须为每个操作传入的每个可能的数字类型创建重载方法 。

因为每个可能的byteshortcharintfloatdouble可以表示为double它更有效(因为它是一个原语而不是任何对象)并且更简单地使用double而不是Number如果你需要特定的类型需要long或BigDecimal或BigInteger。

 public int showAllNum(Number i, Number j) { return (int) (i.doubleValue()+j.doubleValue()); }