Java Methods and Arguments
A method reference such as Math::sqrt is a shorthand that names an existing method without calling it at that point.
Running the Line Before Explaining It
This article begins with running code rather than with a definition. The example comes from a Java program that first prints a short message and then prints the result of calling a method named sum. The call passes three arguments: the method reference Math::sqrt, followed by the integers 1 and 100.
- The first statement prints the descriptive text without moving to a new line.
- The second statement calls sum with three arguments and prints whatever sum returns.
- The argument Math::sqrt is a method reference, not a call to sqrt.
Watch the order in which this line does its work. As you trace it, keep one question in mind: where does the value that gets printed come from? Most of this article answers that question for the unfamiliar part of the line, which is the argument Math::sqrt. The source material's own version of this example is not reproduced exactly here, so the shape above is an illustration of the same structure.
Reading the Expression From Left to Right
A method reference is a shorthand way to refer to an existing method or constructor in Java. Instead of writing out a full piece of code that calls the method, you name the method directly. In the expression Math::sqrt, the name refers to the sqrt method and does not call it at the point where it appears.
Read the expression from left to right. The part before the double colon names the class, here Math. The double colon marks a method reference. The part after it names the method, here sqrt. Together they say: use the sqrt method from the Math class. Because there are no parentheses and no arguments written after sqrt, the expression is a reference rather than a call.
A method reference such as Math::sqrt is a shorthand that names an existing method without calling it at that point. The part before :: names the class, and the part after :: names the method.
Where the Reference Gets Handed Off
A functional interface is an interface that has a single abstract method. According to the source, functional interfaces are the targets that accept lambda expressions or method references. This is why Math::sqrt can appear inside the call to sum. The method reference does not stand alone. It is handed to a place in the program that expects a functional interface, and that place decides what kind of method reference fits.
The diagram shows the general pattern. The caller creates no new sqrt call on its own line; it passes the reference along. The receiving code is the one that eventually invokes sqrt, at the moment it needs a value. The source does not show the declaration of sum, so the exact parameter type is not stated here; what the source does establish is that the reference is passed to a parameter whose type is a functional interface.
Tracing the Argument List
Tracing System.out.println(sum(Math::sqrt, 1, 100))
Find where the printed value is produced in the line that passes Math::sqrt to sum.
- 1Evaluate the arguments
The first argument is the method reference Math::sqrt. It names sqrt without calling it. The second and third arguments are the integers 1 and 100.
- 2Make the call that produces a value
sum is called with those three arguments. This is the step where a value is computed, and it is the value that becomes the result of the call.
- 3Print the value
The result returned by sum is passed to
System.out.println, which displays it. The earlier print call has already printed the descriptive text, so the number appears on the same line.
The printed value is produced by the call to sum. println only displays it. The method reference is one of the inputs that sum receives, so it helps determine that value without itself being run on its own line.
The source describes this trace as the way to follow the line: evaluate the arguments first, then the call that produces a value, then the print statement that displays it. Applying that order is the practical method for answering the question you were asked to keep in mind at the start.
Reference Versus Call
The difference between a reference and a call is easy to miss because the two look similar. The source's key rule is that the absence of parentheses and arguments after the method name is what makes Math::sqrt a reference rather than a call.
| Form | What it is | Runs sqrt right now? |
|---|---|---|
| Math::sqrt | Method reference that names sqrt | No |
| Math.sqrt(x) | Method call with an argument | Yes |
| Math::sqrt() | Written with parentheses, so it reads as a call rather than a plain reference | Not as a plain reference |
Comparing the three forms that look similar on the page.
Common mistake Reading Math::sqrt as if the method has already run
What it looks likeAssuming that Math::sqrt produces a number on the line where it appears
Why it failsThe source states that a method reference names an existing method without calling it at that point.
Do this insteadRead the expression as a name. The value comes later, when the receiving code invokes the method.
Common mistake Adding parentheses to a method reference
What it looks likeWriting Math::sqrt() when a reference was intended
Why it failsThe source identifies the lack of parentheses and arguments as what makes the expression a reference rather than a call.
Do this insteadDrop the parentheses when you want the reference, and keep them only when you want an actual call with arguments.
Common mistake Swapping the class and the method
What it looks likeReading sqrt::Math as if sqrt were the class
Why it failsThe part before the double colon names the class and the part after it names the method.
Do this insteadRead left to right: Math is the class, sqrt is the method.
Common mistake Expecting any value to accept a method reference
What it looks likePassing Math::sqrt to a parameter whose type is not a functional interface
Why it failsMethod references are targets for functional interfaces, which have a single abstract method.
Do this insteadCheck that the receiving parameter is a functional interface before deciding a reference fits there.
Checking Your Trace
Given the line System.out.println(sum(Math::sqrt, 1, 100)); identify the class named by the method reference, the method it names, and the step in which the printed value is produced. Explain why Math::sqrt on this line does not run sqrt by itself.
Hints
- Read the reference from left to right: the part before :: is the class and the part after it is the method.
- Follow the order from the source: evaluate the arguments, then make the call that produces a value, then print it.
- The reference has no parentheses, so it is passed along rather than called on its own line.
Key Takeaways
- A method reference such as Math::sqrt names an existing method without calling it at that point.
- In Math::sqrt, the part before the double colon names the class (Math) and the part after it names the method (sqrt).
- Method references are passed to places that expect a functional interface, which has a single abstract method.
- To trace a line with a method reference, evaluate the arguments first, then the call that produces a value, then the print statement that displays it.
- Parentheses and arguments after the method name are what turn an expression into a call rather than a reference.