除了重写算术运算符之外,还有其他方法可以在Java中实现“溢出安全”算术运算吗?

时间:2014-09-08 18:13:40

标签: java overloading integer-overflow integer-arithmetic

所以这是我的问题。由于我学习了Java,我已经意识到算术溢出和下溢可能存在,java编译器不会向你抱怨。现在我想出一个具有"溢出安全"的操作类。整数+, - ,*方法。因此,如果计算确实溢出,它将抛出算术异常。

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编写的。但我认为我可以使用转换器将其转换为其他语言。虽然不能保证是错误的 - 免费。)我唯一的目标是允许我的旧程序使用"溢出安全"算术运算,无需将所有a + b重新分解为Operation.aDD(a, b)

非常感谢!

3 个答案:

答案 0 :(得分:3)

您可以使用Xtend。您可以将Xtend视为Java语言预处理器。它生成纯粹的,人类可读的Java代码。

关于Xtend中的operator overloading的章节。下面是整数运算符'+'的重载方法定义的示例:

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好得多,但不如vanilla Java好。在调试器中评估变量有一些怪癖。使用Xtend插件,您可以看到实时转换为Xtend代码的纯Java代码。没有Idea的插件。与Maven完美整合。

<强>替代

Xtend本身基于Xtext,这是一个易于创建新语言的框架。使用它和Xbase你可以相对容易地创建一种与Java完全相同的新语言,除了运算符'+'将转换为你想要的任何东西。还有更陡峭的学习曲线,你必须阅读大部分Xtext文档。

答案 1 :(得分:1)

正如您已经发现的那样,您可以使用java中没有运算符重载。

从那以后,直接在纯java中改变表达式int a = b + c;的语义是不可能的。

由于您提到已经拥有C ++代码,因此根据其结构的原因,您可能希望从中构建本机库(DLL,SO)并使用JNI来调用C ++代码。如果你的C ++代码由许多函数/类组成,那么本机调用增加的混乱将超过代码重用的效用,这变得不切实际。毋庸置疑,您需要为要部署的每个平台提供适当的二进制文件。

对于纯Java实现,您需要将逻辑 - 正如您已经想到的那样 - 重写为执行检查的显式实用程序方法调用。

核心java库(例如BigInteger,BigDecimal)更进一步,将它们的类型封装到(通常是不可变的)值对象中,这些值对象仍然作为标准方法调用进行操作。这使得使用更紧凑/更短,因为编译器将提供更多类型检查,您不需要使用类名BigDecimal sum = a.add(b);限定方法名称。不是很漂亮,但它是一个成熟的习语。

答案 2 :(得分:0)

另一种选择可能是混合使用Java和Scala。使用Scala你可以做你说的(我没有Scala的实际经验,但它应该相当容易),加上两者的混合是微不足道的。

参见例如Scala: method\operator overloading

然后,如果您编写了重载算术函数库,只需通过导入Scala包就可以从Java中调用它们,就像在Java中一样。