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

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

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

Java不需要“运算符重载”,因为没有语言需要它。

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

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

Scala是一种较新的JVM语言,其语法允许方法重载,其function与运算符重载非常相似,没有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) 

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

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

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

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

需要空格可能会略微简化词法分析器 – 但是就它而言,它完全独立于运算符重载,至少假设运算符重载是在C ++中完成的,其中只使用现有的标记1

那么,如果那不是问题,那是什么? 运算符重载的问题是您无法对解析器进行硬编码以了解运算符的含义。 对于Java,对于给定的a = b + c ,有两种可能性: ab和c各自从一小组有限的类型中选择,并且该+的含义被烘焙到语言中,否则你有错误。 因此,需要查看b + c并理解它的工具可以进行非常小的解析,以确保bc是可以添加的类型。 如果是,它知道添加意味着什么,它产生什么样的结果,等等。 如果它们不是,它可以用红色曲线(或其他)强调它以指示错误。

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

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

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


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

java-oo编译器插件可以在Java中添加运算符重载支持。

Java不支持程序员的运算符重载。 这与声明Java不需要运算符重载不同。

运算符重载是语法糖,用于表示使用(算术)符号的操作。 出于显而易见的原因,Java编程语言的设计者选择省略对语言中的运算符重载的支持。 可以在Java语言环境白皮书中找到此声明:

程序员没有提供重载标准算术运算符的方法。 再一次,通过声明一个类,适当的实例变量和操作这些变量的适当方法,可以很容易地实现运算符重载的效果。 消除运算符重载可以极大地简化代码。

我个人认为,这是一个明智的决定。 考虑以下代码:

 String b = "b"; String c = "c"; String a = b + c; 

现在,很明显bc连接起来产生a 。 但是,如果考虑使用支持运算符重载的假设语言编写的以下代码段,则很明显使用运算符重载不会产生可读代码。

 Person b = new Person("B"); Person c = new Person("C"); Person a = b + c; 

为了理解上述操作的结果,必须查看Person类的重载加法运算符的实现。 当然,这会导致繁琐的调试会话,并且代码更好地实现为:

 Person b = new Person("B"); Person c = new Person("C"); Person a = b.copyAttributesFrom(c); 

并不是java不需要“运算符重载”,它只是由其创建者做出的选择,他们希望保持语言更简单。

好吧……我们有一个非常讨论和常见的问题。 今天,在软件行业,主要有两种不同类型的语言:

  • 低级语言
  • 高级语言

这种区别在大约10年前是有用的,目前的情况有点不同。 今天我们讨论业务就绪应用程序。 商业模式是一些特定的模型,其中程序需要满足许多要求。 它们非常复杂和严格,以至于使用c或c ++这样的语言编写应用程序将花费大量时间。 出于这个原因,发明了混合语言。

我们通常知道两种语言:

  • 编译
  • 解读

那么,今天又有一个:

  • 编译/解释:用一个词:MANAGED。

托管语言是为了生成另一个代码而编译的语言,这些代码与原始代码不同,但处理起来要复杂得多。 这个中级语言然后由运行最终程序的程序进行插入。

这是我们从Java中了解到的常见动态…它是一种适用于业务就绪应用程序的成功方法。 那么,现在回答你的问题……

运算符重载是一个涉及多级inheritance和低级语言的其他高级特性的问题。 Java,以及C#,Python等,是一种托管语言,易于编写,可用于在极短的时间内构建复杂的应用程序。 如果我们在Java中包含运算符重载,则语言将变得更加复杂且难以处理。

如果你用C ++编程,你肯定明白运算符重载是一个非常非常微妙的问题,因为它可能导致非常复杂的情况,有时编译器可能会因为冲突而拒绝编译等等……引入运算符重载是要小心的。 它很强大,但我们付出了这么大的力量,需要处理大量的问题。

OKOK它是真的,你可能会告诉我:“嘿,但C#使用运算符重载……你到底告诉我什么?为什么c#支持它们而Java不支持?”。 嗯,这就是答案。 C#,是的,实现了运算符重载,但它不像C ++。 有许多运算符不能在c#中重载,比如“new”或许多其他你可以在c ++中重载…所以C#支持运算符重载,但是比c ++或其他完全支持它的语言要低得多。 但这对早期的问题不是一个好的答案……真正的答案是C#比Java更复杂。 这是一个专业人士,但也是一个骗局。 决定语言的位置是一个问题:高水平,高水平,非常高水平? 好吧,Java不支持op重载,因为它希望快速且易于管理和使用。 在引入op重载时,语言还必须承载由此新function引起的大量问题。

这就像质疑:“为什么Java不支持多重inheritance?” 因为管理起来非常复杂。 考虑一下……对于托管语言来说,支持多重inheritance是不可能的……没有公共类树,没有对象类作为所有类的公共基类,没有可能向上转换(安全)和许多问题需要处理,管理,预见,保持计数……

Java想要简单。 即使我相信这种语言的未来实现将导致支持op重载,您将看到重载动态将涉及到有关C ++重载的所有可能性的更少集合。

这里的许多其他人也告诉你,重载是没用的。 嗯,我属于那些认为这不正确的人。 好吧,如果你这样认为(op重载是没用的),那么托管语言的许多其他function也是无用的。 想想接口,类等等,你真的不需要它们。 你可以使用抽象类进行接口实现……让我们看一下c#…这么多糖语法,LINQ等等,它们并不是真的有必要,但是它们很快你的工作……好吧,在托管语言中,一切都要紧固欢迎开发过程,并不意味着无用。 如果您认为这些function没有用,那么整个语言本身就没用了,我们都会回来用c ++,ada等编写复杂的应用程序。托管语言的附加值应该直接在这些元素上进行测量。

Op重载是一个非常有用的function,它可以用Java等语言实现,这会改变语言结构和目的,这将是一件好事,但也是一件坏事,只是一个品味问题。 但是今天,Java比C#更简单,因为Java不支持op重载。

我知道,也许我有点长,但希望它有所帮助。 再见

Java不支持运算符重载(一个引用是Wikipedia Operator Overloading页面)。 这是Java创建者的一项设计决策,旨在避免在其他语言(特别是C ++)中运算符重载时出现的问题。

检查从C和C ++中删除的Javafunction p 2.2.7不再有运算符重载。

程序员没有提供重载标准算术运算符的方法。 再一次,通过声明一个类,适当的实例变量和操作这些变量的适当方法,可以很容易地实现运算符重载的效果。 消除运算符重载可以极大地简化代码。