This document proposes changes to the Java Language Specification to allow use of the var keyword with lambda parameters. See JEP 323 for an overview.

8.4.1 Formal Parameters

The formal parameters of a method or constructor, if any, are specified by a list of comma-separated parameter specifiers. Each parameter specifier consists of a type (optionally preceded by the final modifier and/or one or more annotations) and an identifier (optionally followed by brackets) that specifies the name of the parameter.

If a method or constructor has no formal parameters, only an empty pair of parentheses appears in the declaration of the method or constructor.

FormalParameterList:

ReceiverParameter
FormalParameters , LastFormalParameter
LastFormalParameter
FormalParameter { , FormalParameter }

FormalParameters:

FormalParameter { , FormalParameter }
ReceiverParameter { , FormalParameter }

FormalParameter:

{ VariableModifier } UnannType VariableDeclaratorId
ReceiverParameter
VariableArityParameter

VariableModifier:

Annotation
final

ReceiverParameter:

{ Annotation } UnannType [ Identifier . ] this

LastFormalParameter: VariableArityParameter:

{ VariableModifier } UnannType { Annotation } ... VariableDeclaratorId Identifier
FormalParameter

The following productions from 4.3 and 8.3 are shown here for convenience:

VariableDeclaratorId:

Identifier [ Dims ]

Dims:

{ Annotation } [ ] { { Annotation } [ ] }

The use of var with lambda parameters introduces yet another variation on possible syntactic forms in a parameter list. A lot of complexity in the grammar comes from its attempts to control the order in which these syntactic forms can appear. As a simplifying refactoring, the grammars for parameter lists have been rearranged and no longer enforce ordering. Instead, these constraints are enforced with semantic rules, described below.

The last formal parameter of a method or constructor is special: it may be a variable arity parameter, indicated by an ellipsis following the type.

Note that the ellipsis (...) is a token unto itself (3.11). It is possible to put whitespace between it and the type, but this is discouraged as a matter of style.

If the last formal parameter is a variable arity parameter, the method is a variable arity method. Otherwise, it is a fixed arity method.

The receiver parameter is an optional syntactic device for an instance method or an inner class's constructor. For an instance method, the receiver parameter represents the object for which the method is invoked. For an inner class's constructor, the receiver parameter represents the immediately enclosing instance of the newly constructed object. Either way, the receiver parameter exists solely to allow the type of the represented object to be denoted in source code, so that the type may be annotated. The receiver parameter is not a formal parameter; more precisely, it is not a declaration of any kind of variable (4.12.3), it is never bound to any value passed as an argument in a method invocation expression or qualified class instance creation expression, and it has no effect whatsoever at run time.

The rules for annotation modifiers on a formal parameter declaration and on a receiver parameter are specified in 9.7.4 and 9.7.5.

It is a compile-time error if final appears more than once as a modifier for a formal parameter declaration.

It is a compile-time error to use mixed array notation (10.2) for a variable arity parameter.

This rule is now enforced by the grammar.

It is a compile-time error if a VariableArityParameter appears in a FormalParameterList in a position other than the last element of the list.

The scope and shadowing of a formal parameter is specified in 6.3 and 6.4.

It is a compile-time error for a method or constructor to declare two formal parameters with the same name. (That is, their declarations mention the same Identifier.)

It is a compile-time error if a formal parameter that is declared final is assigned to within the body of the method or constructor.

A receiver parameter may appear only in the FormalParameterList of an instance method or an inner class's constructor; otherwise, a compile-time error occurs.

It is a compile-time error if a ReceiverParameter appears in a FormalParameterList in a position other than the first element of the list.

Where a receiver parameter is allowed, its type and name are specified as follows:

...

15.27.1 Lambda Formal Parameters

The formal parameters of a lambda expression may have either declared types or inferred types be expressed as either a list of comma-separated parameter specifiers or a list of comma-separated identifiers. In the latter case, if there is just one identifier, the parentheses surrounding the list may be elided. These styles cannot be mixed: it is not possible for a lambda expression to declare the types of some of its parameters but leave others to be inferred. Only parameters with declared types can have modifiers. Modifiers may not be applied to the elements of an identifier list.

LambdaParameters:

Identifier
( [ FormalParameterList LambdaParameterList ] )
( InferredFormalParameterList IdentifierList )
Identifier

LambdaParameterList:

LambdaParameter { , LambdaParameter }

LambdaParameter:

{ VariableModifier } LambdaParameterType VariableDeclaratorId
VariableArityParameter

LambdaParameterType:

UnannType
var

InferredFormalParameterList: IdentifierList:

Identifier { , Identifier }

The following productions from 4.3, 8.3, and 8.4.1 are shown here for convenience:

FormalParameterList:

ReceiverParameter
FormalParameters , LastFormalParameter
LastFormalParameter

FormalParameters:

FormalParameter { , FormalParameter }
ReceiverParameter { , FormalParameter }

FormalParameter:

{ VariableModifier } UnannType VariableDeclaratorId

LastFormalParameter: VariableArityParameter:

{ VariableModifier } UnannType { Annotation } ... VariableDeclaratorId Identifier
FormalParameter

VariableModifier:

Annotation
final

VariableDeclaratorId:

Identifier [ Dims ]

Dims:

{ Annotation } [ ] { { Annotation } [ ] }

Receiver parameters are not permitted in the FormalParameters of a lambda expression, as specified in 8.4.1.

This rule is now enforced by the grammar.

If a formal parameter of a lambda expression lacks a declared type, because it is declared either in an identifier list or with a parameter specifier that uses var in place of a type, the parameter's type will be inferred (15.27.3) from the functional interface type targeted by the lambda expression.

A lambda expression whose formal parameters have declared types is said to be explicitly typed, while a lambda expression whose formal parameters have inferred types is said to be implicitly typed. A lambda expression with zero parameters is explicitly typed.

It is a compile-time error if the parameter list of a lambda expression includes both a parameter with a declared type and a parameter with an inferred type.

If the formal parameters have inferred types, then these types are derived (15.27.3) from the functional interface type targeted by the lambda expression.

The syntax for formal parameters with declared types is the same as the syntax for the parameters of a method declaration (8.4.1).

The declared type of a formal parameter depends on whether it is a variable arity parameter (8.4.1):

No distinction is made between the following lambda parameter lists:

(int... x) -> ..
(int[] x) -> ..

Consistent with the rules for overriding, either can be used, whether the functional interface's abstract method is fixed arity or variable arity. Since lambda expressions are never directly invoked, introducing int... where the functional interface uses int[] can have no impact on the surrounding program. In a lambda body, a variable arity parameter is treated just like an array-typed parameter.

The rules for annotation modifiers on a formal parameter declaration are specified in 9.7.4 and 9.7.5.

It is a compile-time error if final appears more than once as a modifier for a formal parameter declaration.

It is a compile-time error to use mixed array notation (10.2) for a variable arity parameter.

This rule is now enforced by the grammar.

It is a compile-time error if a VariableArityParameter appears in a LambdaParameterList in a position other than the last element of the list.

The scope and shadowing of a formal parameter declaration is specified in 6.3 and 6.4.

It is a compile-time error for a lambda expression to declare two formal parameters with the same name.

In Java SE 8, the use of _ as the name of a lambda parameter was forbidden, and its use discouraged as the name for other kinds of variable (4.12.3). As of Java SE 9, _ is a keyword (3.9) so it cannot be used as a variable name in any context.

It is a compile-time error if a receiver parameter (8.4.1) appears in the FormalParameters of a lambda expression.

This rule is now enforced by the grammar.

It is a compile-time error if the LambdaParameterType of a formal parameter is var and the VariableDeclaratorId of the same formal parameter has one or more bracket pairs.

It is a compile-time error if a formal parameter that is declared final is assigned to within the body of the lambda expression.

When the lambda expression is invoked (via a method invocation expression (15.12)), the values of the actual argument expressions initialize newly created parameter variables, each of the declared or inferred type, before execution of the lambda body. The Identifier that appears in the VariableDeclaratorId or the InferredFormalParameterList IdentifierList may be used as a simple name in the lambda body to refer to the formal parameter.

A lambda parameter of type float always contains an element of the float value set (4.2.3); similarly, a lambda parameter of type double always contains an element of the double value set. It is not permitted for a lambda parameter of type float to contain an element of the float-extended-exponent value set that is not also an element of the float value set, nor for a lambda parameter of type double to contain an element of the double-extended-exponent value set that is not also an element of the double value set.

When the parameter types of a lambda expression are inferred, the same lambda body can be interpreted in different ways, depending on the context in which it appears. Specifically, the types of expressions in the body, the checked exceptions thrown by the body, and the type correctness of code in the body all depend on the parameters' inferred types. This implies that inference of parameter types must occur "before" attempting to type-check the body of the lambda expression.