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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3559563/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 01:51:28  来源:igfitidea点击:

Why doesn't Java need Operator Overloading?

javaoperator-overloading

提问by pure.java

Why doesn't Java need operator overloading? Is there any way it can be supported in Java?

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

采纳答案by Sanjay Manohar

Java only allows arithmetic operations on elementary numeric types. It's a mixed blessing, because although it's convenient to define operators on other types (like complex numbers, vectors etc), there are always implementation-dependent idiosyncrasies. So operators don't always do what you expect them to do. By avoiding operator overloading, it's more transparent which function is called when. A wise design move in some people's eyes.

Java 只允许对基本数字类型进行算术运算。这是喜忧参半,因为尽管在其他类型(如复数、向量等)上定义运算符很方便,但总是存在依赖于实现的特性。所以运营商并不总是做你期望他们做的事情。通过避免运算符重载,何时调用哪个函数变得更加透明。一些人眼中的明智设计。

回答by James Curran

Java doesn't "need" operator overloading, because no language needsit.

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

a + bis just "syntactic sugar" for a.Add(b)(actually, some would argue that a.Add(b)is just syntactic sugar for Add(a,b))

a + b只是“语法糖” for a.Add(b)(实际上,有些人会争辩说这a.Add(b)只是 for 的语法糖Add(a,b)

回答by Aaron Novstrup

This related questionmight help. In short, operator overloading was intentionally avoided when Java was designed because of issues with overloading in C++.

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

Scala, a newer JVM language, has a syntax that allows methodoverloading that functions very much like operator overloading, without the limitations of C++ operator overloading. In Scala, it's possible to define a method named +, for example. It's also possible to omit the .operator and parentheses in method calls:

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)

回答by GreenMatt

Java doesn't support operator overloading (one reference is the Wikipedia Operator Overloadingpage). This was a design decision by Java's creators to avoid perceived problems seen with operator overloading in other languages (especially C++).

Java 不支持运算符重载(一个参考是维基百科运算符重载页面)。这是 Java 的创建者的一个设计决定,目的是避免在其他语言(尤其是 C++)中看到的运算符重载问题。

回答by Incognito

Check Java Features Removed from C and C++p 2.2.7 No More Operator Overloading.

检查从 C 和 C++ 中删除的 Java 功能p 2.2.7 No More Operator Overloading。

There are no means provided by which programmers can overload the standard arithmetic operators. Once again, the effects of operator overloading can be just as easily achieved by declaring a class, appropriate instance variables, and appropriate methods to manipulate those variables. Eliminating operator overloading leads to great simplification of code.

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

回答by Colin Hebert

It's not that java doesn't "need" operator overloading, it's just a choice made by its creators who wanted to keep the language more simple.

并不是说 java 不需要“运算符重载”,这只是它的创建者想要保持语言更简单的选择。

回答by Vineet Reynolds

Java does not support operator overloading by programmers. This is not the same as stating that Java does not need operator overloading.

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

Operator overloading is syntactic sugar to express an operation using (arithmetic) symbols. For obvious reasons, the designers of the Java programming language chose to omit support for operator overloading in the language. This declaration can be found in the Java Language Environment whitepaper:

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

There are no means provided by which programmers can overload the standard arithmetic operators. Once again, the effects of operator overloading can be just as easily achieved by declaring a class, appropriate instance variables, and appropriate methods to manipulate those variables. Eliminating operator overloading leads to great simplification of code.

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

In my personal opinion, that is a wise decision. Consider the following piece of code:

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

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

Now, it is fairly evident that band care concatenated to yield a. But when one consider the following snippet written using a hypothetical language that supports operator overloading, it is fairly evident that using operator overloading does not make for readable code.

现在,很明显bc连接到 yield a。但是,当考虑使用支持运算符重载的假设语言编写的以下代码段时,很明显使用运算符重载不会使代码可读。

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

In order to understand the result of the above operation, one must view the implementation of the overloaded addition operator for the Person class. Surely, that makes for a tedious debugging session, and the code is better implemented as:

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

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

回答by Jerry Coffin

No language needsoperator overloading. Some believe that Java wouldbenefit from adding it, but its omission has been publicized as a benefit for so long that adding it is almost certainly politically unacceptable (and it's only since the Oracle buyout that I'd even include the "almost").

没有语言需要运算符重载。有些人认为 Java从添加它中受益,但它的遗漏已经被宣传为一种好处,以至于添加它几乎肯定在上是不可接受的(而且只有在 Oracle 收购之后,我才将“几乎”包括在内)。

The counterpoint generally consists of postulating some meaningless (or even counterintuitive) overload, such as adding together two employees or overloading '+' to do division. While operator overloading in such languages as C++ would allow this, lack of operator overloading in Java does little to prevent or even mitigate the problem. someEmployee.Add(anotherEmployee)is no improvement over someEmployee + anotherEmployee. Likewise, if myLargeInteger.Add(anotherLargeInteger)actually does division instead of addition. At least to me, this line of argument appears thoroughly unconvincing at best.

对位通常包括假设一些无意义(甚至违反直觉)的重载,例如将两个员工加在一起或重载“+”以进行除法。虽然像 C++ 这样的语言中的运算符重载允许这样做,但 Java 中缺少运算符重载对防止甚至减轻这个问题几乎没有作用。 someEmployee.Add(anotherEmployee)是没有改善了someEmployee + anotherEmployee。同样,如果myLargeInteger.Add(anotherLargeInteger)实际上是除法而不是加法。至少在我看来,这种论点充其量是完全没有说服力的。

There is, however, another respect in which omitting operator overloading does (almost certainly) have a real benefit. Its omission keeps the language easier to process, which makes it much easier (and quicker) to develop tools that process the language. Just for an obvious example, refactoring tools for Java are much more numerous and comprehensive than for C++. I doubt that this can or should be credited specifically and solely to support for operator overloading in C++ and its omission in Java. Nonetheless, the general attitude of keeping Java simple (including omission of operator overloading) is undoubtedly a major contributing factor.

然而,在另一个方面,省略运算符重载确实(几乎可以肯定)有真正的好处。它的省略使语言更易于处理,这使得开发处理该语言的工具变得更加容易(和更快)。举一个明显的例子,Java 的重构工具比 C++ 的要多得多,也更全面。我怀疑这是否可以或应该被特别地和完全地归功于支持 C++ 中的运算符重载及其在 Java 中的省略。尽管如此,保持 Java 简单的一般态度(包括省略运算符重载)无疑是一个主要的促成因素。

The possibility of simplifying parsing by requiring spaces between identifiers and operators (e.g., a+bprohibited, but a + ballowed) has been raised. At least in my opinion, this is unlikely to make any real difference in most cases. The reason is fairly simple: at least in a typical compiler, the parser is preceded by a lexer. The lexer extracts tokens from the input stream and feeds them to the parser. With such a structure, the parser wouldn't see any difference at all between the a+band a + b. Either way, it would receive exactly three tokens: identifer, +, and identifier.

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

Requiring the spaces mightsimplify the lexer a tiny bit--but to the extent it did, it would be completely independent of operator overloading, at least assuming the operator overloading was done like it is in C++, where only existing tokens are used1.

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

So, if that's not the problem, what is? The problem with operator overloading is that you can't hard-code a parser to know the meaning of an operator. With Java, for some given a = b + c, there are exactly two possibilities: a, band c are each chosen from a small, limited set of types, and the meaning of that +is baked into the language, or else you have an error. So, a tool that needs to look at b + cand make sense of it can do a veryminimal parse to assure that band care of types that can be added. If they are, it knows what the addition means, what kind of result it produces, and so on. If they are't, it can underline it in red squiggles (or whatever) to indicate an error.

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

For C++, things are quite different. For an expression like a = b + c;, band ccould be of almost entirely arbitrary types. The +could be implemented as a member function of b's type, or it could be a free function. In some cases, we might have a number of operator overloads (some of which could be templates) that couldcarry out that operation, so we need to do overload resolution to determine which one the compiler would actually select based on the types of the parameters (and if some of them are templates, the overload resolution rules get even more complex).

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

That lets us determine the type of the result from b + c. From there we basically repeat the whole process again to figure out what (if any) overload is used to assign that result to a. It might be built-in, or it might be another operator overload, and there might be multiple possible overloads that could do the job, so we have to do overload resolution again to figure out the right operator to use here.

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

In short, just figuring out what a = b + c;means in C++ requires nearly an entire compiler front-end. We can do the same in Java with a muchsmaller subset of a compiler2

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



  1. I suppose things could be somewhat different if you allowed operator overloading like, for example, ML does, where a more or less arbitrary token can be designated as an operator, and that operator can be given a more or less arbitrary associativity and/or precedence. I believe ML handles this entirely in parsing, not lexing, but if you took this basic concept enough further, I can believe it might start to affect lexing, not just parsing.
  2. Not to mention that most Java tools will use the JDK, which has a complete Java compiler built into the JVM, so tools can normally do most such analysis without dealing directly with parsing and such at all.
  1. 我想如果您允许运算符重载(例如 ML),则情况可能会有所不同,其中或多或少可以将任意标记指定为运算符,并且可以为该运算符或多或少赋予任意关联性和/或优先级. 我相信 ML 完全在解析中处理这个问题,而不是词法分析,但是如果您将这个基本概念进一步理解,我可以相信它可能会开始影响词法分析,而不仅仅是解析。
  2. 更不用说大多数 Java 工具将使用 JDK,它在 JVM 中内置了一个完整的 Java 编译器,因此工具通常可以完成大多数此类分析,而无需直接处理解析等。

回答by Andry

OK Well... we have a very discussed and common issue. Today, in software industry, there are, mainly, two different types of languages:

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

  • Low level languages
  • High level languages
  • 低级语言
  • 高级语言

This distinction was useful about 10 years before now, the situation, at present, is a bit different. Today we talk about business-ready applications. Business models are some particular models where programs need to meet many requirements. They are so complex and so strict that coding an application with a language like c or c++ would be very time-spending. For this reason hybrid languages where invented.

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

We commonly know two types of languages:

我们通常知道两种类型的语言:

  • Compiled
  • Interpreted
  • 已编译
  • 口译

Well, today there is another one:

好吧,今天还有一个:

  • Compiled/Interpreted: in one word: MANAGED.
  • 编译/解释:一个词:管理。

Managed languages are languages that are compiled in order to produce another code, different from the original one, but much more complex to handle. This INTERMEDIATE LANGUAGE is then INTERPETED by a program that runs the final program.

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

It is the common dynamics we came knowing from Java... It is a winning approach for business-ready applications. Well, now going to your question...

这是我们从 Java 中了解到的共同动态……这是业务就绪应用程序的成功方法。好吧,现在开始你的问题......

Operator overloading is a matter that concerns also multiple inheritance and other advanced characteristics of low level languages. Java, as well as C#, Python and so on, is a managed language, made to be easy to write and useful for building complex applications in very few time. If we included operator overloading in Java, the language would become more complex and difficult to handle.

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

If you program in C++ you sure understand that operator overloading is a very very very delicate matter because it can lead to very complex situations and sometimes compiler might refuse to compile because of conflicts and so on... Introducing operator overloading is to be done carefully. IT IS POWERFUL, but we pay this power with an incredibly big load of problems to handle.

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

OKOK IT IS TRUE, you might tell me: "HEY, But C# uses operator overloading... What the hell are you telling me? why c# supports them and Java not?". Well, this is the answer. C#, yes, implements operator overloading, but it is not like C++. There are many operator that cannot be overloaded in c# like "new" or many others that you can overload in c++... So C# supports operator overloading, but in a much lower level than c++ or other languages that fully supports it. But this is not a good answer to the earlier question... The real answer is that C# is more complex than Java. This is a pro but also a con. It is a matter of deciding where to place the language: high level, higher level, very high level? Well, Java does not support op overloading because it wants to be fast and easy to manage and use. When introducing op overloading, a language must also carry a large amount of problems caused by this new functionality.

好的,这是真的,你可能会告诉我:“嘿,但是 C# 使用运算符重载......你到底在告诉我什么?为什么 c# 支持它们而 Java 不支持?”。嗯,这就是答案。C#,是的,实现了运算符重载,但它不像 C++。有许多运算符不能在 c# 中重载,如“new”或许多其他运算符,您可以在 c++ 中重载……所以 C# 支持运算符重载,但比 C++ 或其他完全支持它的语言低得多。但这对前面的问题不是一个好的答案......真正的答案是 C# 比 Java 更复杂。这是一个优点,但也是一个缺点。这是决定将语言放在哪里的问题:高级、高级、非常高级?好吧,Java 不支持操作重载,因为它希望快速且易于管理和使用。

It is exactly like questioning: "Why does Java not support multiple inheritance?" Because it is tremendously complex to manage. Think about it... IT WOULD BE IMPOSSIBLE for a managed language to support multiple inheritance... No common class tree, no object class as a common base class for all classes, no possibility of upcasting (safely) and many problems to handle, manage, foresee, keep in count...

就像提问:“为什么Java不支持多重继承?” 因为管理起来非常复杂。想一想......托管语言不可能支持多重继承......没有公共类树,没有对象类作为所有类的公共基类,没有向上转换(安全)的可能性以及需要处理的许多问题,管理,预见,计数......

Java wants to be simple. Even if I believe that future implementations of this language will result in supporting op overloading, you will see that the overloading dynamics will involve a fewer set of all the possibilities you have about overloading in C++.

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

Many others, here, also told you that overloading is useless. Well I belong to those ones who think this is not true. Well, if you think this way (op overloading is useless), then also many other features of managed languages are useless too. Think about interfaces, classes and so on, you really do not need them. You can use abstract classes for interface implementations... Let's look at c#... so many sugar syntax, LINQ and so on, they are not really necessary, BUT THEY FASTEN YOUR WORK... Well, in managed languages everything that fasten a development process is welcome and does not imply uselessness. If you think that such features are not useful than the entire language itself would be useless and we all would come back programming complex applications in c++, ada, etc. The added value of managed languages is to be measured right on this elements.

这里的许多其他人也告诉您重载是无用的。好吧,我属于那些认为这不是事实的人。好吧,如果你这样想(操作重载是没有用的),那么托管语言的许多其他特性也没有用。想想接口、类等等,你真的不需要它们。您可以将抽象类用于接口实现...让我们看看 c#... 这么多糖语法、LINQ 等,它们并不是真正必要的,但它们可以加快您的工作...嗯,在托管语言中,一切都可以固定开发过程是受欢迎的,并不意味着无用。如果您认为这些功能没有用,那么整个语言本身将毫无用处,我们都会回来用 c++、ada 等编写复杂的应用程序。

Op overloading is a very useful feature, it could be implemented in languages like Java, and this would change the language structure and purposes, it would be a good thing but a bad thing too, just a matter of tastes. But today, Java is simpler than C# even for this reason, because Java does not supports op overloading.

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

I know, maybe I was a little long, but hope it helps. Bye

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

回答by mart

java-oo compiler plugincan add Operator Overloading support in Java.

java-oo 编译器插件可以在 Java 中添加 Operator Overloading 支持。