简体   繁体   English

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

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

So here is my question. 所以这是我的问题。 Since I learnt Java, I have been aware that arithmetic overflow and underflow can exist and java compiler will not complain it to you. 自从学习Java之后,我就知道算术上溢和下溢可能存在,并且Java编译器不会向您抱怨。 Now I come up with a Operation class which has "overflow safe" integer +, -, * methods in it. 现在,我想到了一个Operation类,其中包含“溢出安全”整数+,-,*方法。 So that if the calculation does overflow, it will throw arithmetic exception. 因此,如果计算确实溢出,则会抛出算术异常。

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;
    }
}

I want to override the original arithmetic operators in Java. 我想覆盖Java中的原始算术运算符。 So that I don't need to type int c = Operation.aDD(a, b); 这样我就不需要键入int c = Operation.aDD(a, b); to use the "overflow safe" arithmetic operations. 使用“溢出安全”算术运算。 Instead, I only need to type int c = a + b; 相反,我只需要输入int c = a + b;

However, I was told user defined operator overriding is not possible in Java. 但是,有人告诉我,在Java中无法进行用户定义的运算符覆盖。 So, is there anyway to achieve the same result without overriding operator in Java. 因此,无论如何,在不重写Java中的运算符的情况下,是否可以获得相同的结果。 Anyway of doing so is acceptable, including mixing Java and C++ code.(Note that all my code is written in Java for now. But I think I can convert it to other language using a converter. Although it is not guaranteed to be bug-free.) My only goal is to allow my older program to use the "overflow safe" arithmetic operations without having to re-factor all the a + b into Operation.aDD(a, b) . 无论如何,这样做都是可以接受的,包括混合Java和C ++代码。(请注意,我的所有代码目前都是用Java编写的。但是我认为我可以使用转换器将其转换为其他语言。尽管不能保证它是bug-我唯一的目标是允许我的旧程序使用“溢出安全”算术运算,而不必将所有a + bOperation.aDD(a, b)

Thanks a lot! 非常感谢!

You can use Xtend . 您可以使用Xtend You can see Xtend as Java language preprocessor. 您可以将Xtend视为Java语言预处理器。 It generates pure, human readable Java code. 它生成纯人类可读的Java代码。

Chapter about operator overloading in Xtend. 有关Xtend中运算符重载的章节。 Here is an example of overloading method definition for operator '+' for integers: 这是整数运算符“ +”的重载方法定义示例:

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

Drawbacks 缺点

Xtend is also a language, there is some small learning curve. Xtend也是一种语言,有一些小的学习曲线。 It is very similar to Java, but also incorporating some bits from Groovy and Scala syntax, like method is defined by keyword 'def', variable by 'var' or 'val', otherwise you can write code same as Java. 它与Java非常相似,但是还结合了Groovy和Scala语法中的一些功能,例如方法是由关键字“ def”定义的,变量是由“ var”或“ val”定义的,否则您可以编写与Java相同的代码。 You can, optionally, use lambda methods, extension methods (like in C#), multiline text literals and many more goodies. 您可以选择使用lambda方法,扩展方法(例如在C#中),多行文本文字和更多其他东西。 Xtend has excellent Eclipse plugin, much better than Scala, but not completely as good as vanilla Java. Xtend具有出色的Eclipse插件,比Scala更好,但不完全像普通Java一样好。 Evaluating variables in debugger had some quirks. 在调试器中评估变量有些怪癖。 With Xtend plugin you can see to what pure Java code is Xtend code translated to in real time. 使用Xtend插件,您可以实时查看Xtend代码被转换成什么纯Java代码。 No plugin for Idea. 没有适用于Idea的插件。 Well integrated with Maven. 与Maven集成良好。

Alternative 另类

Xtend is itself based on Xtext , a framework for easy creation of new languages. Xtend本身基于XtextXtext是一个易于创建新语言的框架。 Using it and Xbase you can relatively easily create a new language which would be exactly same as Java except that operator '+' would translate to whatever you want. 使用它和Xbase,您可以相对轻松地创建一种与Java完全相同的新语言,只是运算符'+'可以转换为您想要的任何语言。 There is much more steep learning curve, you would have to read most of the Xtext documentation then. 学习曲线要​​陡峭得多,然后您必须阅读大多数Xtext文档。

As you already found out, there is no operator overloading in java you can use. 如您所知,在Java中没有可以使用的运算符重载。

From that there follows straight that altering the semantics of an expression int a = b + c; 由此可见,改变表达式的语义int a = b + c; in pure java is simply not possible. 在纯Java中根本不可能。

Since you mention already having C++ code, depending on how its structured you might want to build a native library (DLL, SO) from it and use JNI to call the C++ code. 既然您已经提到了C ++代码,则根据其结构如何,您可能希望从中构建本机库(DLL,SO)并使用JNI调用C ++代码。 It becomes impractical if your C++ code consists of many small functions/classes, the added clutter for native calls would outweight the utility of code reuse. 如果您的C ++代码由许多小的函数/类组成,这将变得不切实际,为本机调用增加的混乱将使代码重用的实用性超过。 Needless to say you will need a proper binary for each platfrom you want to deploy to. 不用说,对于要部署到的每个平台,您将需要一个合适的二进制文件。

For a pure java implementation you will need to rewrite the logic - just as you already figured out - into explicit utility method calls doing the checks. 对于纯Java实现,您将需要将逻辑重写为显式的实用程序方法调用(正如您已经知道的那样),以进行检查。

Core java libraries (eg BigInteger, BigDecimal) go a tiny step farther and encapsulate their types into (usually immutable) value objects that (still) carry operations as standard method calls. 核心Java库(例如BigInteger,BigDecimal)走了很小的一步,并将其类型封装为(通常是不可变的)值对象,这些值对象(仍)作为标准方法调用进行操作。 That makes usage a little more compact/shorter, since the compiler will provide a little more type checking and you would not need to qualify method names with a class name BigDecimal sum = a.add(b); 这使用法更紧凑/更短,因为编译器将提供更多类型检查,并且您不需要使用类名BigDecimal sum = a.add(b);来限定方法名称BigDecimal sum = a.add(b); . Not much prettier, but its a well established idiom. 不太漂亮,但是它是一个成熟的习语。

Another option could be to mix Java and Scala. 另一种选择是将Java和Scala混合使用。 With Scala you can do what you say (I have no real experience with Scala but it should be rather easy), plus mixing the two is trivial. 使用Scala,您可以按照您所说的做(我没有使用Scala的实际经验,但是应该很简单),而且将两者混合在一起是微不足道的。

See for example Scala: method\\operator overloading 参见示例Scala:method \\ operator重载

Then, if you write your library of overloaded arithmetic functions, you can call them from Java simply by importing the Scala package, as you would do in Java. 然后,如果您编写了重载算术函数的库,则可以像在Java中一样,只需导入Scala包就可以从Java中调用它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM