简体   繁体   中英

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. Now I come up with a Operation class which has "overflow safe" integer +, -, * methods in it. 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. So that I don't need to type int c = Operation.aDD(a, b); to use the "overflow safe" arithmetic operations. Instead, I only need to type int c = a + b;

However, I was told user defined operator overriding is not possible in Java. So, is there anyway to achieve the same result without overriding operator in 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) .

Thanks a lot!

You can use Xtend . You can see Xtend as Java language preprocessor. It generates pure, human readable Java code.

Chapter about operator overloading in 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. 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. You can, optionally, use lambda methods, extension methods (like in C#), multiline text literals and many more goodies. Xtend has excellent Eclipse plugin, much better than Scala, but not completely as good as vanilla 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. No plugin for Idea. Well integrated with Maven.

Alternative

Xtend is itself based on Xtext , a framework for easy creation of new languages. 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. There is much more steep learning curve, you would have to read most of the Xtext documentation then.

As you already found out, there is no operator overloading in java you can use.

From that there follows straight that altering the semantics of an expression int a = b + c; in pure java is simply not possible.

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. 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. 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.

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. 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); . Not much prettier, but its a well established idiom.

Another option could be to mix Java and 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.

See for example Scala: method\\operator overloading

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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