为什么我不能用Number接口计算?
Why can't I calculate with Number interface?
我想做这样的class来计算平均值:
public static class AverageValue<T extends Number> {
T data = 0; //ERROR: incompatible types: int cannot be converted to T
int count = 0;
public AverageValue() {}
public AverageValue(T data) {
this.data = data;
count = 1;
}
public void add(T num) {
data+=num; //ERROR: bad operand types for binary operator '+'
count++;
}
public T average() {
return data/(T)count; //ERROR: incompatible types: int cannot be converted to T
}
}
如果 不抽象数字 ,我真的不明白为什么我们有接口 Number。因为这就是接口所做的 - 对数据进行抽象操作而不保存数据本身。
以上内容也清楚地表明,您可能永远无法实现自己的数字实现(例如,对于一些非常怪异的实验性数学程序,数字的大小和精度不受限制)。
我用 Number
而不是通用 T
进行了相同的尝试,结果完全相同。唯一的区别是 Number x = 0
实际上是有效的。
有没有办法欺骗 java 来编译它,或者我必须是 "professional" java 程序员并使用双精度来计算字节数组的平均值?
您混淆了 classes (Number
) 和原始类型 (int
)。数字 classes 不支持 +
或 \
等运算符(字符串支持 +
,但这是一种特殊情况;不同于 C#
, Java 不支持自定义运算符重载。
"number with unlimited size and precision for some really freaky experimental math programs" 实际上受 BigDecimal
class 支持,这表明(以及如何)您确实可以拥有自己的 Number
实现。
ERROR: incompatible types: int cannot be converted to T
T data = (T)(Integer)0;
ERROR: bad operand types for binary operator '+'
ERROR: incompatible types: int cannot be converted to T
在java中不存在运算符重载Why doesn't Java need Operator Overloading?
您可以在 class 中使用 double
s。因为Integers
的平均值是Double
,所以应该是正确的。
public class AverageValue<T extends Number> {
double data = 0;
int count = 0;
public AverageValue() {
}
public AverageValue(T data) {
this.data = data.doubleValue();
count = 1;
}
public void add(T num) {
data += num.doubleValue();
count++;
}
public double average() {
return data / count;
}
}
编译通过。用法:
AverageValue<Integer> avgInt = new AverageValue<>();
avgInt.add(1);
avgInt.add(2);
avgInt.add(3);
avgInt.add(4);
System.out.println(avgInt.average());
AverageValue<Double> avgDouble = new AverageValue<>();
avgDouble.add(1.1);
avgDouble.add(1.2);
avgDouble.add(1.3);
avgDouble.add(1.4);
System.out.println(avgDouble.average());
输出:
2.5
1.25
I am not really getting why do we have interface Number
if it doesn't abstract number
interface Number
确实出于存储和转换表示的目的抽象了数字。它不会为了进行计算而抽象数字,因为结果的类型 表示 没有明确定义。
The above also makes it clear that you'll probably not be ever able to make your own number implementation (eg. number with unlimited size and precision for some really freaky experimental math programs).
BigDecimal
没有任何问题。
Number x = 0
is actually valid.
将 Integer
分配给 Number
就可以了。将 Integer
分配给扩展 Number
的内容(例如,Double
)是不正确的。这就是为什么会有差异。
Is there a way to trick java to compile this or do I have to go full retard professional Java programmer and use doubles to calculate averages on byte arrays?
您需要在计算平均值时指定所需的结果表示形式。您可以自己将其抽象出来并提供 "averager" 界面,但是有关所需表示的信息需要以一种或另一种方式进入方法:
interface AverageMaker<T extends Number> {
T initialResult();
T add(T a, Number b);
T divideByCount(T a, int b);
}
public static <T extends Number, R extends Number> R averageValue(Iterable<T> items, AverageMaker<R> maker) {
R res = maker.initialResult();
int count = 0;
for (T val : items) {
res = maker.add(res, val);
count++;
}
return maker.divideByCount(res, count);
}
定义几个平均庄家,像这样:
static final AverageMaker<Double> doubleAvg = new AverageMaker<Double>() {
public Double initialResult() { return 0.0; }
public Double add(Double a, Number b) { return a + b.doubleValue(); }
public Double divideByCount(Double a, int b) { return a/b; }
};
static final AverageMaker<Integer> intAvg = new AverageMaker<Integer>() {
public Integer initialResult() { return 0; }
public Integer add(Integer a, Number b) { return a + b.intValue(); }
public Integer divideByCount(Integer a, int b) { return a/b; }
};
现在您可以在代码中将它们与 averageValue
方法一起使用:
List<Integer> a = new ArrayList<Integer>();
a.add(4);
a.add(8);
a.add(91);
a.add(18);
double avgDouble = averageValue(a, doubleAvg);
int avgInt = averageValue(a, intAvg);
System.out.println(avgDouble); // Prints 30.25
System.out.println(avgInt); // Prints 30
我想做这样的class来计算平均值:
public static class AverageValue<T extends Number> {
T data = 0; //ERROR: incompatible types: int cannot be converted to T
int count = 0;
public AverageValue() {}
public AverageValue(T data) {
this.data = data;
count = 1;
}
public void add(T num) {
data+=num; //ERROR: bad operand types for binary operator '+'
count++;
}
public T average() {
return data/(T)count; //ERROR: incompatible types: int cannot be converted to T
}
}
如果 不抽象数字 ,我真的不明白为什么我们有接口 Number。因为这就是接口所做的 - 对数据进行抽象操作而不保存数据本身。
以上内容也清楚地表明,您可能永远无法实现自己的数字实现(例如,对于一些非常怪异的实验性数学程序,数字的大小和精度不受限制)。
我用 Number
而不是通用 T
进行了相同的尝试,结果完全相同。唯一的区别是 Number x = 0
实际上是有效的。
有没有办法欺骗 java 来编译它,或者我必须是 "professional" java 程序员并使用双精度来计算字节数组的平均值?
您混淆了 classes (Number
) 和原始类型 (int
)。数字 classes 不支持 +
或 \
等运算符(字符串支持 +
,但这是一种特殊情况;不同于 C#
, Java 不支持自定义运算符重载。
"number with unlimited size and precision for some really freaky experimental math programs" 实际上受 BigDecimal
class 支持,这表明(以及如何)您确实可以拥有自己的 Number
实现。
ERROR: incompatible types: int cannot be converted to T
T data = (T)(Integer)0;
ERROR: bad operand types for binary operator '+'
ERROR: incompatible types: int cannot be converted to T
在java中不存在运算符重载Why doesn't Java need Operator Overloading?
您可以在 class 中使用 double
s。因为Integers
的平均值是Double
,所以应该是正确的。
public class AverageValue<T extends Number> {
double data = 0;
int count = 0;
public AverageValue() {
}
public AverageValue(T data) {
this.data = data.doubleValue();
count = 1;
}
public void add(T num) {
data += num.doubleValue();
count++;
}
public double average() {
return data / count;
}
}
编译通过。用法:
AverageValue<Integer> avgInt = new AverageValue<>();
avgInt.add(1);
avgInt.add(2);
avgInt.add(3);
avgInt.add(4);
System.out.println(avgInt.average());
AverageValue<Double> avgDouble = new AverageValue<>();
avgDouble.add(1.1);
avgDouble.add(1.2);
avgDouble.add(1.3);
avgDouble.add(1.4);
System.out.println(avgDouble.average());
输出:
2.5
1.25
I am not really getting why do we have interface
Number
if it doesn't abstract number
interface Number
确实出于存储和转换表示的目的抽象了数字。它不会为了进行计算而抽象数字,因为结果的类型 表示 没有明确定义。
The above also makes it clear that you'll probably not be ever able to make your own number implementation (eg. number with unlimited size and precision for some really freaky experimental math programs).
BigDecimal
没有任何问题。
Number x = 0
is actually valid.
将 Integer
分配给 Number
就可以了。将 Integer
分配给扩展 Number
的内容(例如,Double
)是不正确的。这就是为什么会有差异。
Is there a way to trick java to compile this or do I have to go full
retardprofessional Java programmer and use doubles to calculate averages on byte arrays?
您需要在计算平均值时指定所需的结果表示形式。您可以自己将其抽象出来并提供 "averager" 界面,但是有关所需表示的信息需要以一种或另一种方式进入方法:
interface AverageMaker<T extends Number> {
T initialResult();
T add(T a, Number b);
T divideByCount(T a, int b);
}
public static <T extends Number, R extends Number> R averageValue(Iterable<T> items, AverageMaker<R> maker) {
R res = maker.initialResult();
int count = 0;
for (T val : items) {
res = maker.add(res, val);
count++;
}
return maker.divideByCount(res, count);
}
定义几个平均庄家,像这样:
static final AverageMaker<Double> doubleAvg = new AverageMaker<Double>() {
public Double initialResult() { return 0.0; }
public Double add(Double a, Number b) { return a + b.doubleValue(); }
public Double divideByCount(Double a, int b) { return a/b; }
};
static final AverageMaker<Integer> intAvg = new AverageMaker<Integer>() {
public Integer initialResult() { return 0; }
public Integer add(Integer a, Number b) { return a + b.intValue(); }
public Integer divideByCount(Integer a, int b) { return a/b; }
};
现在您可以在代码中将它们与 averageValue
方法一起使用:
List<Integer> a = new ArrayList<Integer>();
a.add(4);
a.add(8);
a.add(91);
a.add(18);
double avgDouble = averageValue(a, doubleAvg);
int avgInt = averageValue(a, intAvg);
System.out.println(avgDouble); // Prints 30.25
System.out.println(avgInt); // Prints 30