簡體   English   中英

除了覆蓋算術運算符以外,還有其他方法可以在Java中實現“溢出安全”算術運算嗎?

[英]Is there any other way to implement “overflow safe” arithmetic operations in Java other than overriding arithmetic operators?

所以這是我的問題。 自從學習Java之后,我就知道算術上溢和下溢可能存在,並且Java編譯器不會向您抱怨。 現在,我想到了一個Operation類,其中包含“溢出安全”整數+,-,*方法。 因此,如果計算確實溢出,則會拋出算術異常。

public final class Operation{

    public static int aDD (int a, int b) {
    //do something
    if (overflow) {
    throw ArithmeticException("Integer Addition Overflow");
    }
    return a + b;
    }

    public static int sUB (int a, int b) {
    //do something
    if (overflow) {
    throw ArithmeticException("Integer Subtraction Overflow");
    }
    return a - b;
    }

    public static int mUL (int a, int b) {
    //do something
    if (overflow) {
    throw ArithmeticException("Integer Multiplication Overflow");
    }
    return a * b;
    }

    public static long aDD (long a, long b) {
    //do something
    if (overflow) {
    throw ArithmeticException("Long Addition Overflow");
    }
    return a + b;
    }

    public static long sUB (long a, long b) {
    //do something
    if (overflow) {
    throw ArithmeticException("Long Subtraction Overflow");
    }
    return a - b;
    }

    public static long mUL (long a, long b) {
    //do something
    if (overflow) {
    throw ArithmeticException("Long Multiplication Overflow");
    }
    return a * b;
    }
}

我想覆蓋Java中的原始算術運算符。 這樣我就不需要鍵入int c = Operation.aDD(a, b); 使用“溢出安全”算術運算。 相反,我只需要輸入int c = a + b;

但是,有人告訴我,在Java中無法進行用戶定義的運算符覆蓋。 因此,無論如何,在不重寫Java中的運算符的情況下,是否可以獲得相同的結果。 無論如何,這樣做都是可以接受的,包括混合Java和C ++代碼。(請注意,我的所有代碼目前都是用Java編寫的。但是我認為我可以使用轉換器將其轉換為其他語言。盡管不能保證它是bug-我唯一的目標是允許我的舊程序使用“溢出安全”算術運算,而不必將所有a + bOperation.aDD(a, b)

非常感謝!

您可以使用Xtend 您可以將Xtend視為Java語言預處理器。 它生成純人類可讀的Java代碼。

有關Xtend中運算符重載的章節。 這是整數運算符“ +”的重載方法定義示例:

def static operator_add(IntVar a, IntVar b) {
    return Operation.add(a, b)
}

缺點

Xtend也是一種語言,有一些小的學習曲線。 它與Java非常相似,但是還結合了Groovy和Scala語法中的一些功能,例如方法是由關鍵字“ def”定義的,變量是由“ var”或“ val”定義的,否則您可以編寫與Java相同的代碼。 您可以選擇使用lambda方法,擴展方法(例如在C#中),多行文本文字和更多其他東西。 Xtend具有出色的Eclipse插件,比Scala更好,但不完全像普通Java一樣好。 在調試器中評估變量有些怪癖。 使用Xtend插件,您可以實時查看Xtend代碼被轉換成什么純Java代碼。 沒有適用於Idea的插件。 與Maven集成良好。

另類

Xtend本身基於XtextXtext是一個易於創建新語言的框架。 使用它和Xbase,您可以相對輕松地創建一種與Java完全相同的新語言,只是運算符'+'可以轉換為您想要的任何語言。 學習曲線要​​陡峭得多,然后您必須閱讀大多數Xtext文檔。

如您所知,在Java中沒有可以使用的運算符重載。

由此可見,改變表達式的語義int a = b + c; 在純Java中根本不可能。

既然您已經提到了C ++代碼,則根據其結構如何,您可能希望從中構建本機庫(DLL,SO)並使用JNI調用C ++代碼。 如果您的C ++代碼由許多小的函數/類組成,這將變得不切實際,為本機調用增加的混亂將使代碼重用的實用性超過。 不用說,對於要部署到的每個平台,您將需要一個合適的二進制文件。

對於純Java實現,您將需要將邏輯重寫為顯式的實用程序方法調用(正如您已經知道的那樣),以進行檢查。

核心Java庫(例如BigInteger,BigDecimal)走了很小的一步,並將其類型封裝為(通常是不可變的)值對象,這些值對象(仍)作為標准方法調用進行操作。 這使用法更緊湊/更短,因為編譯器將提供更多類型檢查,並且您不需要使用類名BigDecimal sum = a.add(b);來限定方法名稱BigDecimal sum = a.add(b); 不太漂亮,但是它是一個成熟的習語。

另一種選擇是將Java和Scala混合使用。 使用Scala,您可以按照您所說的做(我沒有使用Scala的實際經驗,但是應該很簡單),而且將兩者混合在一起是微不足道的。

參見示例Scala:method \\ operator重載

然后,如果您編寫了重載算術函數的庫,則可以像在Java中一樣,只需導入Scala包就可以從Java中調用它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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