所以这是我的问题。自从学习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 + b重构为Operation.aDD(a, b)。
非常感谢!
您无法在Java中覆盖运算符。 而且您不能"混合" C / C ++和Java。 您可以在某些困难下在它们之间进行呼叫,但这将比您现在所遇到的要丑陋得多。
您可能会遵循具有相同问题的BigDecimal / BigInteger的命名约定。
您可以使用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本身基于Xtext,Xtext是一个易于创建新语言的框架。使用它和Xbase,您可以相对轻松地创建一种与Java完全相同的新语言,只是运算符'+'可以转换为您想要的任何语言。学习曲线要??陡峭得多,然后您必须阅读大多数Xtext文档。
如您所知,在Java中没有可以使用的运算符重载。
由此可见,在纯Java中根本不可能更改表达式int a = b + c;的语义。
既然您已经提到了C ++代码,则根据其结构如何,您可能希望从中构建本机库(DLL,SO)并使用JNI调用C ++代码。如果您的C ++代码由许多小的函数/类组成,这将变得不切实际,为本机调用增加的混乱将使代码重用的实用性过重。不用说,对于要部署到的每个平台,您将需要一个合适的二进制文件。
对于纯Java实现,您将需要将逻辑重写为显式的实用程序方法调用(正如您已经知道的那样),以进行检查。
核心Java库(例如BigInteger,BigDecimal)进一步走了一步,并将其类型封装到(通常是不可变的)值对象中,这些值对象(仍)以标准方法调用的形式进行操作。这使用法更紧凑/更短,因为编译器将提供更多类型检查,并且您不需要使用类名BigDecimal sum = a.add(b);限定方法名。不太漂亮,但是它是一个成熟的习语。
是否有语言支持Java语法和运算符重载?这样,如果我将Java程序复制到它,它将进行编译。我之所以提到C ++,是因为有人告诉我C ++支持运算符重载。我不是说我的代码是用C ++编写的,如果让您感到困惑,请对不起。
此外,您还提到了BigInteger值对象。我有个主意。我们如何使用MyInteger sum = a.add(b);和MyLong sum = a.add(b);?然后我发现Integer和Long类具有final修饰符,因此我不能使用class MyInteger extends Integer和class MyLong extends Long。我应该复制Integer和Long类并添加自己的方法来创建新类吗?还有另一种方法吗?
@AlexVong Core Java使用不可变值对象(Integer,Long ... BigDecimal ...)。每个操作都会创建一个新对象;例如" z = x.add(y);"返回结果作为新对象z。这个想法是,您可以在任何地方传递值对象引用,而不必担心它们会被修改。
有什么方法可以将方法"放入" Integer类?我想在类中添加一个ADD方法。由于Integer类具有修饰符final,因此我无法使用继承来实现它。
@AlexVong Nope,使java.lang类成为最终类,以防止您弄乱它们的行为(请注意,java编译器依赖于它们为自动装箱/拆箱提供精确指定的行为)。键入自己的类型,也许扩展java.lang.Number。
我将尝试编写MyInteger类
另一种选择是将Java和Scala混合使用。使用Scala,您可以按照您所说的做(我没有使用Scala的实际经验,但是应该很简单),而且将两者混合在一起是微不足道的。
参见示例Scala:method operator重载
然后,如果您编写了重载算术函数的库,则可以像在Java中一样,只需导入Scala包就可以从Java中调用它们。
对不起,让我感到困惑。但是我的方法实际上是用Java编写的,因此如果要使用运算符重载,则需要在Scala中重写它们并导入Operation Class。
也许我不明白这一点。您愿意用C ++重写它们,但不愿意在Scala中重写它们吗?
这是另一个混??乱大声笑。我不用C ++重写它。我将对其进行编辑。
听起来很傻。但是我发现我可以使用转换器。
我确实尝试了您的建议,并为NetBeans安装了Scala插件。但是事实证明,Scala中的Int类具有final和abstract修饰符,因此我无法扩展Int类并覆盖该类中定义的+,-,*运算符。开发人员似乎设置了障碍,以防止有人弄乱他们的代码。您知道如何解决吗?