为什么Java不需要运算符重载?

pur*_*ava 17 java operator-overloading

为什么Java不需要运算符重载?有没有什么方法可以在Java中支持它?

San*_*har 14

Java仅允许对基本数字类型进行算术运算.这是一个混合的祝福,因为虽然在其他类型(如复数,向量等)上定义运算符很方便,但总是存在依赖于实现的特性.因此,运营商并不总能按照您的期望去做.通过避免运算符重载,当更加透明时调用哪个函数.一些人的眼中有明智的设计.

  • 这几乎是正确的,因为它定义了char和字符串类型的加法. (7认同)
  • 从这个答案的逻辑 - 方法名称可能会产生误导,为什么允许程序员给方法一个名字?让我们用数字列举它们! (5认同)
  • 值得注意的是,人们总是可以使用令人困惑的变量名称,比如xyzzy.人们可能使用语言功能来编写混淆代码的简单事实本身不应被视为避免该功能的合理理由,尤其是当该功能可用于创建*更多*可读代码时正确的背景.我觉得很遗憾,不使用Java解决问题的唯一真正原因是数学上最优雅的解决方案(并且数量不是很少)只是因为设计师不希望运算符重载. (3认同)
  • 他们只忘了BigInteger和BigDecimal :( (2认同)
  • @aib:更糟糕的是他们弄错了.C#和Java都使用+进行加法和连接,因此我们得到了奇怪的类型强制错误.它们与Visual Basic在创建Java之前解决了半年的错误相同,它们将它们分成两个运算符. (2认同)
  • 决定 Java 不需要运算符重载的人显然从未尝试过以任意精度计算 ISS 轨道元素。我有。做对了吗?是的。能读懂吗?让我想想。 (2认同)

Jam*_*ran 8

Java不需要"运算符重载",因为没有语言需要它.

a + ba.Add(b)(实际上,有些人认为这a.Add(b)只是语法糖Add(a,b))只是"语法糖"

  • 阅读:a.add(b.minus(h).multiply(d.divide(i.add(j))).add(e)).add(c.multiply(f.minus(g.divide( j))))`现在谁需要`a + b`! (57认同)
  • 根据Java命名约定,方法`add`不应该大写. (12认同)
  • @ firegnom,首先,这就是人们通常会用较少的括号杂乱写出相同的表达式:a +(b - h)*(d /(i + j))+ e + c*(f - g/j )`,是的我说这简单得多了.例如,我可以非常快速地看到正在添加的组件以及正在乘以或除以什么的组件.用`a.op(b)`写的很难看.我不了解你,但是从小学毕业后我就和操作员一起长大,所以当然这对我来说更清楚了. (11认同)
  • 我没有特别谈到Java,而是一般的语言.例如,在Java中,你不能拥有非成员函数Add(a,b) (3认同)
  • 您可以使用静态方法,该方法基本相同. (2认同)
  • 除了语法和易读性之外,运算符在Math中具有优先级。因此,乘法比加法具有更高的优先级。“ a + b * c”将首先执行“ b * c”,然后将其结果添加到“ a”中。运算符重载使处理这些操作更容易,如果没有这些操作,您就必须在编写方法时考虑优先级顺序。 (2认同)

Aar*_*rup 7

这个相关问题可能有所帮助 简而言之,由于C++中的重载问题,在设计Java时有意避免了运算符重载.

Scala是一种较新的JVM语言,其语法允许方法重载,其功能与运算符重载非常相似,没有C++运算符重载的限制.例如,在Scala中,可以定义一个名为的方法+.也可以.在方法调用中省略运算符和括号:

case class A(value: Int) {
   def +(other: A) = new A(value + other.value)
}

scala> new A(1) + new A(3)                                                           
res0: A = A(4)
Run Code Online (Sandbox Code Playgroud)


Jer*_*fin 5

没有语言需要运算符重载.有些人认为Java 因为添加它而受益,但是它的遗漏已被宣传为长期以来的好处,因此添加它几乎肯定是政治上不可接受的(并且只有在甲骨文收购之后我甚至包括"差不多").

对应点通常包括假设一些无意义(或甚至违反直觉)的重载,例如将两个雇员加在一起或重载'+'来进行分工.虽然运算符使用C++等语言进行重载可以实现这一点,但Java中缺少运算符重载几乎无法阻止甚至缓解问题. someEmployee.Add(anotherEmployee)没有改善someEmployee + anotherEmployee.同样,如果myLargeInteger.Add(anotherLargeInteger)实际上是分裂而不是添加.至少在我看来,这一论点充其量只是令人难以置信.

然而,另一方面,省略运算符重载(几乎可以肯定)具有真正的好处.它的省略使语言更容易处理,这使得开发处理语言的工具变得更容易(也更快).仅举一个明显的例子,Java的重构工具比C++更加丰富和全面.我怀疑这可以或应该被认可,仅仅是为了支持C++中的运算符重载及其在Java中的遗漏.尽管如此,保持Java简单(包括忽略运算符重载)的一般态度无疑是一个主要因素.

通过在标识符和运算符之间要求空格(例如,a+b禁止但a + b允许)来简化解析的可能性已经提出.至少在我看来,这在大多数情况下不太可能产生任何真正的差别.原因很简单:至少在典型的编译器中,解析器前面有一个词法分析器.词法分析器从输入流中提取标记并将它们提供给解析器.有了这样的结构,解析器就不会看到a+b和之间的任何差异a + b.无论哪种方式,这样会得到恰好三个令牌:identifer,+,和identifier.

需要的空间可能简化词法分析器一点点-但它没有的程度,这将是完全独立的操作符重载,至少假设操作符重载做像它是在C++中,其中仅现有令牌用于1.

那么,如果那不是问题,那是什么?运算符重载的问题在于您无法对解析器进行硬编码以了解运算符的含义.使用Java,对于某个给定的a = b + c,恰好有两种可能性:a,b和C分别由一个小的,有限的几个类型选择,并且该含义+被烤成的语言,否则你有一个错误.因此,需要一种工具来看待b + c和意义的它可以做一个非常最小的解析,以确保bc是可以添加的类型.如果是,它知道添加意味着什么,它产生什么样的结果,等等.如果它们不是,它可以用红色曲线(或其他)强调它以指示错误.

对于C++,情况完全不同.对于表达等a = b + c;,bc可以是几乎完全任意的类型.所述+可以被实现为的成员函数b的类型,或者它可以是一个免费的功能.在某些情况下,我们可能会有许多操作符重载(其中一些可能是模板)可以执行该操作,因此我们需要执行重载决策以确定编译器根据参数类型实际选择哪一个(如果其中一些是模板,则重载决策规则变得更加复杂).

这让我们可以确定结果的类型b + c.从那里我们基本上再次重复整个过程,以找出用于分配结果的(如果有的话)重载a.它可能是内置的,或者可能是另一个运算符重载,并且可能有多个可能的重载可以完成这项工作,因此我们必须再次进行重载解析以找出在此使用的正确运算符.

简而言之,只是弄清楚a = b + c;C++中的含义几乎需要整个编译器前端.我们可以在Java中使用小的编译器子集2来做同样的事情


  1. 我想如果你允许运算符重载,例如ML就可以有些不同,其中可以将或多或少的任意标记指定为运算符,并且该运算符可以被赋予或多或少的任意关联性和/或优先级.我相信ML完全在解析中处理它,而不是lexing,但是如果你进一步充分考虑这个基本概念,我可以相信它可能会开始影响lexing,而不仅仅是解析.
  2. 更不用说大多数Java工具将使用JDK,它具有内置于JVM中的完整Java编译器,因此工具通常可以执行大多数此类分析,而无需直接处理解析等等.

  • 尝试使用BigInteger进行大量工作,您可能会开始认识到可能所有运算符重载都不错. (3认同)