java.lang.Number 没有实现“+”或任何其他运算符?
Posted
技术标签:
【中文标题】java.lang.Number 没有实现“+”或任何其他运算符?【英文标题】:java.lang.Number doesn't implement "+" or any other operators? 【发布时间】:2012-02-15 23:55:57 【问题描述】:我正在创建一个类,它应该能够与任何类型的数字(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;
除了这不会编译,因为“数字”没有实现“+=”或“/=”运算符。更糟糕的是,Java 的 Number 类甚至没有实现最基本的运算符,如“+”或“-”!如果java不让我编译它,我怎么能创建一个返回数字数组平均值的方法,因为它认为不能添加数字?!?!
【问题讨论】:
Java 没有像 C++ 这样的重载运算符。它所拥有的是方法。例如,java.lang.BigInteger 有一个名为“add”的方法。 欢迎来到 Java,这里的操作符不是函数。此外,您应该了解type erasure,因为Java 中的泛型根本不像C++ 中的模板那样工作。 顺便说一下,数字是抽象的。你甚至无法实例化它。 Nothing 实现了操作符;它们是语言/句法结构。字符串是特殊情况下的语法糖。 @PaulTomblin 除了+
能够连接字符串
【参考方案1】:
您误解了 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 自动为 boxing and unboxing Integer
,因为 +=
运算符仅适用于原始类型。它之所以有效是因为我们明确指出该数字是Integer
,但它不适用于Number
,因为Java 需要准确地知道它正在处理的数字类型什么执行装箱/拆箱。
【讨论】:
除了不使用算术运算符之外,Number API 不提供任何执行算术的方法。【参考方案2】:您需要将数字转换为原始类型,然后算术运算符才能工作。您会注意到Number
确实有doubleValue
、intValue
等......
或者,您可以转换为BigDecimal
,并使用该类上定义的算术方法(不是+
、-
等,而是add
、multiply
, 等等....)。这种方法会更准确(如果您需要最佳准确度,请使用BigDecimal
),因为浮点数和双精度数仅表示一组离散的数值。请记住,BigDecimal 是不可变的,因此您始终需要将操作的结果分配给引用。
【讨论】:
如果他要明确转换为double
、int
等,那么他到底为什么要使用Number
开头呢?我不认为这是解决方案。【参考方案3】:
我想这就是你想要的
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;
【讨论】:
【参考方案4】:很遗憾,你不能。算术运算符仅适用于原始类型(这要归功于其包装器上的自动装箱和自动拆箱)。您必须为需要该方法处理的所有原始类型覆盖给定的方法,就像在许多 JDK 类中所做的那样。
【讨论】:
【参考方案5】:在 Java 中,算术运算符仅适用于原始类型。这里的问题是 Java 具有这些原始类型的类表示,并且通过称为 autoboxing 的功能从一个到另一个的切换通常是隐式的。
在这种情况下,您需要为所需的算术运算类型实现方法,可能必须为每个运算传入的每个可能的数字类型创建 overloaded methods。
【讨论】:
【参考方案6】:由于所有可能的byte
、short
、char
、int
、float
、double
都可以表示为double
,因此它的效率更高(因为它是一个原语而不是任何对象)并且更易于使用 double
而不是 Number
如果您需要准确的 long
或 BigDecimal 或 BigInteger,则需要特定的类型。
【讨论】:
@KennethNoland 你能举个例子说明这些类型的值不能存储在 double 中而不丢失精度吗? double 至少有 53 位精度,足以存储任何这些类型。【参考方案7】:public int showAllNum(Number i, Number j)
return (int) (i.doubleValue()+j.doubleValue());
【讨论】:
您应该正确格式化并解释您的答案。以上是关于java.lang.Number 没有实现“+”或任何其他运算符?的主要内容,如果未能解决你的问题,请参考以下文章