Lambda Specification, Part C: Method and Constructor References

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

Summary

A method reference is used to refer to a method without invoking it; a constructor reference is similarly used to refer to a constructor without creating a new instance of the named class or array type.

Examples of method and constructor references:

System::getProperty
"abc"::length
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 an inner class instance must be provided for a constructor reference 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.28 Method and Constructor Reference Expressions [New]

A method reference is used to refer to a method without invoking it; a constructor reference is similarly used to refer to a constructor without creating a new instance of the named class or array type.

MethodReference:
 ExpressionName '::' NonWildTypeArgumentsopt Identifier
 Primary '::' NonWildTypeArgumentsopt Identifier
 'super' '::' NonWildTypeArgumentsopt Identifier
 TypeName '.' 'super' '::' NonWildTypeArgumentsopt Identifier
 ReferenceType '::' NonWildTypeArgumentsopt Identifier

ConstructorReference:
 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 the ClassType of a constructor reference denotes a class that is an enum type or that is abstract. [jsr335-15.28-10]

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 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 an inner class instance (15.9.2) must be provided for a constructor reference 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.

If a method or constructor is generic, the reference expression may refer to the method or constructor either generically or as a particular parameterization, depending on the functional interface type targeted by the expression. In the latter case, the appropriate type arguments may either be inferred or provided explicitly. Similarly, the type arguments of a generic type mentioned by the reference expression may be provided explicitly or inferred.

Examples of method and constructor reference expressions:
System::getProperty
String::length
List<String>::size   // explicit class type args
List::size           // inferred class type args, or generic
int[]::clone
T::tvarMember

"abc"::length
foo[x]::bar
(test ? list.map(String::length) : Collections.emptyList())::iterator
super::toString

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

ArrayList<String>::new    // constructor for parameterized type
ArrayList::new            // inferred class type args, or generic
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 "constructor"
Discussion and motivation:
  1. It would be convenient to have a single name to talk about both method and constructor references. Unfortunately, there is no similar terminology for generalizing about both methods and constructors. Some compiler APIs use executable, but this hasn't been standardized in the JLS. Method reference by itself ignores the constructor case (kind of like class to refer to both classes and interfaces). Reference expression evokes C++ & references. Function reference could work, but it makes more sense interpreted as "a function defined in terms of a reference" rather than the more natural but less accurate reading, "a reference to a thing that is a function." Member reference would be ideal, except that constructors are not considered members.
  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 JLS 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.28 is currently the last section in chapter 15 and defines constant expressions. To reasonably accommodate the chapter structure without drastically changing section numbers, this has been bumped forward to 15.29 and 15.28 has been repurposed to address method and constructor references.

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
  ...
  ','
  '.'
  '::'