25

In Java 8 method references are done using the :: operator.

For Example

// Class that provides the functionality via it's static method
public class AddableUtil {
  public static int addThemUp(int i1, int i2){
    return i1+i2;
  }
}

// Test class
public class AddableTest {
  // Lambda expression using static method on a separate class
  IAddable addableViaMethodReference = AddableUtil::addThemUp;
  ...
}

You can see that the addableViaMethodReference now acts like an alias to AddableUtil::addThemUp. So addableViaMethodReference() will perform the same action as AddableUtil.addThemUp() and return the same value.

Why did they choose to introduce a new operator instead of using an existing one ? I mean, execute a function when the function name ends with () and return the function reference when there is no trailing ().

Method Execution

AddableUtil.addThemUp();

Method reference

AddableUtil.addThemUp;

Wouldn't this be much simpler and intuitive ? AFAIK, AddableUtil.addThemUp doesn't currently (Java 7) serve any other purpose and throws a compilation error. Why not use that opportunity instead of creating an entirely new operator ?

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
ShaggyInjun
  • 2,880
  • 2
  • 31
  • 52
  • 23
    `AddableUtil.addThemUp` is a public field – guido Oct 27 '14 at 15:04
  • 3
    @ShaggyInjun nope; you always need to ask questions (to others and to yourself) to understand things and improve. even if the answer may look silly, having asked politely and nicely, you did even get upvotes. – guido Oct 27 '14 at 15:11
  • 7
    Of course, the compiler could distinguish between the two uses cases if it wanted to (public field access vs method reference). But the introduction of a new operator makes it easier for developers to see what is happening. – Duncan Jones Oct 27 '14 at 15:12
  • 1
    **explicit is better than implicit**, other than my opinion, like everyone else that might answer is only **opinion**. Email Oracle if you want an answer. This is **off topic** here! –  Oct 27 '14 at 15:15
  • 2
    Java keeps fields and methods very different, for some reasons that are probably historical. Most modern languages don't, and a method is simply a field that can also be called. (which java still can't, apparently, and thanks to this syntax). – njzk2 Oct 27 '14 at 15:15
  • 8
    @JarrodRoberson I believe this is completely answerable. There either is or isn't a technical reason (I believe there is, albeit pedantic), therefore the only logical conclusion is that it is to avoid confusion. I really don't think there's much room for opinion here (since we aren't discussing why *that particular* operator was chosen). – Duncan Jones Oct 27 '14 at 15:19
  • @JarrodRoberson explicit is better than implicit would be an opinion-based answer, but asking if there was any technically cause for not reusing an operator is perfectly ontopic here. – guido Oct 27 '14 at 15:21
  • 1
    @Duncan - that is **your opinion**, kind of proves my point, whether is a technical reason or not isn't the issue, it is **opinion** on the question of **why they did it this way and not the way suggested**, that is **purely speculation and opinion**. And your edit does not make this any less opinion based speculation either, you just removed the **why didn't they just** part. Canonical answer only exists with who made the decision at Oracle. –  Oct 27 '14 at 15:21
  • 2
    @JarrodRoberson I can post a piece of code (and was just about to before it closed) that wouldn't work if the operator hadn't changed. Seems conclusive to me. As soon as this opens (and I suspect it will), I will post it. Please feel free to inspect it. *Wishing gold hammers worked on reopenings...* – Duncan Jones Oct 27 '14 at 15:22
  • 1
    @JarrodRoberson The question is definitive & so is the answer from @Guido. Now I am not arguing there are no speculative replies but that doesn't discount the definitive answer by any means. Wasn't asking why oracle chose `::` as opposed to `అ`. – ShaggyInjun Oct 27 '14 at 15:22
  • 3
    I don't agree with this as "opinion-based" either. Surely, there's some objective technical reason why dot-notation couldn't be used. @njzk2 mentions other modern language offer exactly this type of functionality (e.g. C# properties and Scala def/val uniformity). – Chris Scott Oct 27 '14 at 15:22
  • 2
    `AddableUtil.addThemUp` may be 1) a package, 2) a class or 3) a member variable. It’s already like magic that Java figures out the right thing (well, almost) when using a qualified name (the naming conventions help here). But adding the possibility that it may also refer to a method would be a nightmare. But it *is* opinion based as even the question contains an opinion: that using `.` instead of `::` was ever considered (i.e. that the dot was “more intuitive”). – Holger Oct 27 '14 at 15:22
  • @JarrodRoberson Any particular reason you [rolled back my edit](http://stackoverflow.com/posts/26590453/revisions)? I don't want to start an edit war, but I'm quite tempted to roll-back your roll-back, unless you can defend it. – Duncan Jones Oct 27 '14 at 15:25
  • @Duncan - you completely put all the comments out context without improving the quality of the question just like my edit comment states. –  Oct 27 '14 at 15:27
  • 2
    @JarrodRoberson I can't see your edit comment, system must squash it when you roll back. Regardless, my edit was at 15:10, which predates all but two of the comments in this thread. It also doesn't substantially change the meaning of the post, since it's clear from the content of the question (e.g. "*Why did they choose to introduce a new operator instead of using an existing one*") that the question is not about the specific choice of operator. The title edit is also a distinct improvement on the predecessor. For those reasons, I'm rolling back again. – Duncan Jones Oct 27 '14 at 15:31
  • 1
    I'm confident that @Duncan can provide a persuasive example for the technical necessity of a new operator, so I vote for "reopen", too. – Erich Kitzmueller Oct 27 '14 at 15:44

3 Answers3

33

The following piece of code compiles fine in Java 8, but would be ambiguous without a new operator:

import java.util.function.IntBinaryOperator;

public class A {

  public static IntBinaryOperator addThemUp;

  public static int addThemUp(int i1, int i2) {
    return i1 + i2;
  }

  public static void main(String[] args) throws Exception {
    IntBinaryOperator operator = A::addThemUp;
  }
}

It wouldn't be clear whether A.addThemUp refers to the public IntBinaryOperator field or is an attempt to create a method reference.

Yes, it's a bit contrived. But you can't allow edge cases in programming language syntax.

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
  • Shouldn't the field be static, too? (Edit: the answer was edited a few seconds after my comment, so I'm not sure if it was because of my comment...) – Erich Kitzmueller Oct 27 '14 at 15:46
  • @guido Sorry for stealing your thunder. But I figured a worked example would help and I had no idea if you had one. You may spot a few suspicious up-votes on your account soon.. ;-) – Duncan Jones Oct 27 '14 at 15:47
  • 1
    @Duncan, just make it community wiki and it's all fair – bestsss Oct 27 '14 at 15:48
  • @ammoQ, it doesn't matter if it's static as that could have been a bug in the code prior introducing the :: operator – bestsss Oct 27 '14 at 15:49
  • @bestsss I see no reason to do that. It still took time and effort to produce a worked example. If someone would like to post a better answer they are always welcome. I realise, of course, this response makes it seem like I care about a few upvotes, which at 25k I really don't. I mostly dislike how CW answers are editable by pretty much everyone. – Duncan Jones Oct 27 '14 at 15:50
  • Compilers can deal with this type of ambiguity so this is still an opinion. (Though it is a reasonable suggestion because the Java language typically steers away from ambiguity.) – Radiodef Oct 27 '14 at 15:54
  • @Radiodef Are you suggesting a well-documented order of precedence that would mean one of those options would be deterministically chosen? If so, I agree, but I think you are stretching the "opinion-based" a little - Java could have already done that with other constructs (such as methods that differ only in return type etc.) but chose not to. [Edit: just seen your edited final sentence, so it seems we agree mostly] – Duncan Jones Oct 27 '14 at 15:56
  • Yes the JLS could specify which would be chosen given such an ambiguity or it would fail to compile (due to ambiguity at the reference expression or declaring duplicate identifiers at the class). What I am objecting to is that a few people think this must be the 'one true answer' when that can't be determined. Surely it has to do with methods and fields being treated semantically different in the Java language (and therefore syntactically) but ambiguity is not actually a problem, just an inconvenience. – Radiodef Oct 27 '14 at 16:15
  • 1
    @bestsss if the field isn't static, there is no ambiguity in the example – Erich Kitzmueller Oct 27 '14 at 16:44
  • 6
    Actually, you can allow edge cases in programming language syntax, but then you end up with Perl, and nobody wants that. ;) – David Conrad Oct 27 '14 at 18:16
20

Fields and methods have separate name spaces, so there is the possibility of an ambiguity between a method name and a field name (which might then require even more rules to disambiguate). This is definitely a big problem for the "reuse some existing syntax" approach (which was, BTW, considered as a candidate, as were a number of other possibilities.)

But, I would turn the question around: is "overloading" an existing syntax like this really a good idea? (Your question assumes this, but this is an enormous assumption.) There's a big difference between "call method m / read field f" and "refer to method m / field f by name". Shouldn't the two kinds of expressions look different? What is the benefit of reusing an existing syntax to mean something completely different?

Further, there's a scalability issue with the approach you suggest: we'd never be able to do field references in the future without inventing a new syntax, which would then be different from the syntax for method references. While field references were not a must-have for lambda, never being able to finish the job here would be a big minus.

These are just a few of the various considerations that fed into this decision. In hindsight, I still think we made the right call here.

Brian Goetz
  • 90,105
  • 23
  • 150
  • 161
  • 6
    Further proof this is not worthy of closure - you can't rule out Oracle folks passing by with authoritative answers. +1 – Duncan Jones Oct 27 '14 at 17:19
  • Out of interest, were there contenders to `::` that narrowly missed out? – Duncan Jones Oct 27 '14 at 17:39
  • 3
    @Duncan My memory, as a mostly-lurker on the lambda-dev mailing list, was that `#` was being considered, but they decided to reserve that for potential future uses. IIRC there were even lambda builds that used it. – David Conrad Oct 27 '14 at 18:18
  • Thanks Brian, that was a very detailed answer and helped me understand finer details & considerations. – ShaggyInjun Oct 27 '14 at 19:38
  • 6
    We considered various infix syntaxes other than ::, as well as various prefix syntaxes (like &Foo.bar). Foo#bar was a better fit when the lambda syntax also used #, but when the syntax went to a more C#/Scala-style, became less attractive. – Brian Goetz Oct 27 '14 at 21:00
  • I do agree that introducing a new syntax was a good idea in the context of Java and even necessary as detailed in [this answer](http://stackoverflow.com/a/26591296/402281). But I would not count using the `.` operator as "overloading". Depending on how you look at it, the `.` operator is not what is making it a function call (field access and lots of other syntaxes use that operator) but rather the parenthesis after an identifier are. – Feuermurmel Nov 27 '14 at 13:06
1

Maybe they did it to make the C++ programmers feel more welcome in Java? /* In my opinion (dangerous words to use as a skeptic), operator:: is more natural to use on static methods, as it is the scope resolution operator in C++ */

Mike Warren
  • 3,796
  • 5
  • 47
  • 99
  • 6
    Nice theory! But actually, the biggest complaint about `::` was "Ick, it makes my Java code look like C++" (and not in a good way.) But, one of the reasons it was chosen was that languages that use `::` use it as a "selector" operation, so its use in method references seemed a natural fit. – Brian Goetz Oct 29 '14 at 21:20