Lambda Specification, Part C: Method References

Navigation: Overview - Part A - Part B - Part C - Part D - Part E - Part F - Part G - Part H - Part J
Sections: 15.13 - 3.11
Version 0.9.3. Copyright © 2014 Oracle America, Inc. Legal Notice.

Summary

A method reference is used to refer to the invocation of a method without actually performing the invocation. Certain forms of method references also allow class instance creation or array creation to be treated as if it were a method invocation.

Examples of method references:

System::getProperty
"abc"::length
System.out::println
String::length
super::toString
ArrayList::new
int[]::new

The target reference (i.e., the "receiver") of an instance method may be provided by the method reference expression or it may be provided later when the method is invoked. The immediately enclosing instance of a new inner class instance must be provided by a lexically enclosing instance of this.

When more than one member method of a type has the same name, or when a class has more than one constructor, the appropriate method or constructor is selected based on the functional interface type targeted by the expression.

15.13 Method Reference Expressions [New]

A method reference is used to refer to the invocation of a method without actually performing the invocation. Certain forms of method references also allow class instance creation (15.9) or array creation (15.10) to be treated as if it were a method invocation.

MethodReference:
 ExpressionName '::' NonWildTypeArgumentsopt Identifier
 Primary '::' NonWildTypeArgumentsopt Identifier
 'super' '::' NonWildTypeArgumentsopt Identifier
 TypeName '.' 'super' '::' NonWildTypeArgumentsopt Identifier
 ReferenceType '::' NonWildTypeArgumentsopt Identifier
 ClassType '::' NonWildTypeArgumentsopt 'new'
 ArrayType '::' 'new'

The following productions from 8.8.7.1 are repeated here for convenience:

NonWildTypeArguments:
 '<' ReferenceTypeList '>'

ReferenceTypeList:
 ReferenceType
 ReferenceTypeList ',' ReferenceType

It is a compile-time error if a method reference has the form ExpressionName :: NonWildTypeArgumentsopt Identifier or Primary :: NonWildTypeArgumentsopt Identifier, and the type of the ExpressionName or Primary is not a reference type. [jsr335-15.28-5]

If a method reference has the form super :: NonWildTypeArgumentsopt Identifier, let T be the type declaration immediately enclosing the method reference. It is a compile-time error if T is the class Object or T is an interface. [jsr335-15.28-21]

If a method reference has the form TypeName . super :: NonWildTypeArgumentsopt Identifier, then: [jsr335-15.28-22]

The above restrictions mimic 15.12.1 (as modified by this specification). (We could avoid stating them here, because 15.13.1 is defined in terms of 15.12.1, but it's more straightforward to be explicit about it.)

It is a compile-time error if a method reference of the form super :: NonWildTypeArgumentsopt Identifier or of the form TypeName . super :: NonWildTypeArgumentsopt Identifier occurs in a static context. [jsr335-15.28-20]

The above restriction mimics 15.12.3.

If a method reference has the form ClassType :: NonWildTypeArgumentsopt new, the ClassType must denote a class that is accessible (6.6) and is not an enum type and not abstract, or a compile-time error occurs. [jsr335-15.28-10]

The above restriction mimics 15.9.1.

In addition, if a method reference has the form ClassType :: NonWildTypeArgumentsopt new, it is a compile-time error if any of the type arguments used in the ClassType are wildcard type arguments (4.5.1). [jsr335-15.28-11]

It is a compile-time error If a method reference has the form ClassType :: NonWildTypeArguments new, where a constructor type argument list is provided, but the ClassType is a raw type. [jsr335-15.28-12]

The above restrictions mimic 15.9.

If a method reference has the form ArrayType :: new, the ArrayType must denote a type that is reifiable (4.7), or a compile-time error occurs. [jsr335-15.28.15]

The above restriction mimics 15.10.

The target reference of an instance method (15.12.4.1) may be provided by the method reference expression—using an ExpressionName, a Primary, or super—or it may be provided later when the method is invoked. The immediately enclosing instance of a new inner class instance (15.9.2) must be provided by a lexically enclosing instance of this (8.1.3).

When more than one member method of a type has the same name, or when a class has more than one constructor, the appropriate method or constructor is selected based on the functional interface type targeted by the expression, as described in 15.13.1.

If a method or constructor is generic, the appropriate type arguments may either be inferred or provided explicitly. Similarly, the type arguments of a generic type mentioned by the method reference may be provided explicitly or inferred.

Examples of method reference expressions:

System::getProperty
String::length
List<String>::size   // explicit class type args
List::size           // inferred class type args
int[]::clone
T::tvarMember

"abc"::length
System.out::println
foo[x]::bar
(test ? stream.map(String::trim) : stream)::toArray
super::toString

String::valueOf      // overload resolution needed     
Arrays::sort         // type args inferred from context
Arrays::<String>sort // explicit type args

ArrayList<String>::new    // constructor for parameterized type
ArrayList::new            // inferred class type args
Foo::<Integer>new         // explicit generic constructor type arguments
Bar<String>::<Integer>new // generic class, generic constructor
Outer.Inner::new          // inner class constructor
int[]::new                // array creation

Discussion and motivation:

  1. The term "method reference" is imprecise, but captures the typical usage of the feature. In full generality, method references are shorthand to describe certain expressions that should not be evaluated until a future point. Hence, the same method can be referenced via a standard invocation or a super invocation—properties of the implicit invocation expression, not the method itself. Similarly, class instance creation and array creation can be referenced, even though there is no actual corresponding method that returns a class instance or an array.
  2. There is no support for specifying a particular signature to be matched:
    Arrays::sort(int[])

    Instead, the functional interface provides argument types that are used as input to the overload resolution algorithm (15.12.2). This should satisfy the vast majority of use cases; when the rare need arises for more precise control, a lambda expression can be used.

  3. The method reference delimiter is infix; this seems useful because it clearly separates the "evaluated now" portion of the expression from the "evaluated on invocation" part. It also conveys the useful model that a method reference is sort of like a new kind of member of an object or class.

    Other languages simply use a method name as a method reference—the delimiter would be '.'. But this introduces ambiguities with field names, so it is useful to have a unique delimiter to differentiate.

  4. The use of type argument syntax in the class name before a delimiter (List<String>::size) raises the parsing problem of distinguishing between '<' as a type argument bracket and '<' as a less-than operator; this problem does not arise in a static method invocation. In theory, this is no worse than allowing type arguments in cast expressions; however, the difference is that the cast case only comes up when a '(' token is encountered; with the addition of method references, the start of every expression is potentially a parameterized type.
  5. Section 15.13 currently addresses array access expressions. To make room for method reference expressions, this section has been merged with 15.10.

3.11 Separators [Modified]

Compare JLS 3.11

Nine Ten tokens, formed from ASCII characters, are the separators (punctuators). [jls-3.11-100]

Separator: one of
  ...
  ','
  '.'
  '::'