簡體   English   中英

為什么無法使用Number接口進行計算?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM