Concepts / Java Methods and Arguments

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.

  • Programming

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.

java
Notes on the code
  • 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.

Mathclass that holds the method::method reference operatorsqrtmethod being named, notcalled
How do I tell apart a reference that names a method (Math::sqrt) from a call that runs it right now (Math.sqrt(x)), and what is each part of the reference pointing to?

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.

Definition

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.

Calling lineprintln of sum resultsum methodreceives the referenceFunctional interfaceparameterexpects a single abstractmethodMath sqrtruns when invokedpasses Math::sqrt, 1, 100hands over referenceinvokes sqrt on a valuereturns a resultreturns value to println
When I pass Math::sqrt into a method that expects a functional interface, who holds the reference and who actually invokes sqrt, and when?

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

Worked example

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.

  1. 1
    Evaluate 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.

  2. 2
    Make 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.

  3. 3
    Print 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.

Result

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.

FormWhat it isRuns sqrt right now?
Math::sqrtMethod reference that names sqrtNo
Math.sqrt(x)Method call with an argumentYes
Math::sqrt()Written with parentheses, so it reads as a call rather than a plain referenceNot 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 like

    Assuming that Math::sqrt produces a number on the line where it appears

    Why it fails

    The source states that a method reference names an existing method without calling it at that point.

    Do this instead

    Read 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 like

    Writing Math::sqrt() when a reference was intended

    Why it fails

    The source identifies the lack of parentheses and arguments as what makes the expression a reference rather than a call.

    Do this instead

    Drop 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 like

    Reading sqrt::Math as if sqrt were the class

    Why it fails

    The part before the double colon names the class and the part after it names the method.

    Do this instead

    Read left to right: Math is the class, sqrt is the method.

  • Common mistake

    Expecting any value to accept a method reference

    What it looks like

    Passing Math::sqrt to a parameter whose type is not a functional interface

    Why it fails

    Method references are targets for functional interfaces, which have a single abstract method.

    Do this instead

    Check that the receiving parameter is a functional interface before deciding a reference fits there.

Checking Your Trace

MEDIUM

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.