[英]Why can't I calculate with Number interface?
我想做這樣的類來計算平均值:
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進行編譯,還是必須成為“專業” Java程序員並使用雙精度來計算字節數組的平均值?
我們我不是真的越來越為什么非得接口
Number
,如果它不是抽象的數字
interface Number
會提取數字以用於存儲和轉換表示形式。 由於結果表示的類型定義不明確,因此不會出於計算目的而提取數字。
上面的內容還清楚地表明,您可能將永遠無法實現自己的數字實現(例如,對於某些非常怪異的實驗數學程序,數字的大小和精度沒有限制)。
BigDecimal
可以毫無問題地做到這一點。
Number x = 0
實際上是有效的。
將Integer
分配給Number
是可以的。 將Integer
分配給擴展Number
(例如Double
)是不可行的。 這就是為什么存在差異的原因。
有沒有一種方法來欺騙的Java編譯這個還是我必須去全面
減速專業的Java程序員和使用雙打來計算字節數組平均值?
計算平均值時,需要指定所需的結果表示形式。 您可以自己將其抽象出來並提供“ 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
您正在混合類( Number
)和基本類型( int
)。 數字類不支持+
或\\
等運算符(字符串支持+
,但這是一種特殊情況;與C#
不同,Java不支持自定義運算符重載)。
BigDecimal
類實際上支持“對於某些非常怪異的實驗數學程序,其大小和精度不受限制的數字”,它表明(以及如何)您確實可以擁有自己的Number
實現。
您可以在課堂上使用double
。 由於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
錯誤:不兼容的類型:int無法轉換為T
T data = (T)(Integer)0;
錯誤:二進制運算符'+'的錯誤操作數類型
錯誤:不兼容的類型:int無法轉換為T
Java中不存在運算符重載為什么Java不需要運算符重載?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.