繁体   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