JSR 335: Lambda Expressions for the Java™ Programming Language

Version 0.9.1. Copyright © 2013 Oracle America, Inc. Legal Notice.

Outline

Introduction

This document presents the language and virtual machine specification changes for JSR 335: Lambda Expressions for the Java™ Programming Language.

The new language features are described with reference to existing structure and definitions in the Java Language Specification, Java SE 7 Edition. Unless stated otherwise, section numbers interspersed throughout the document refer to the Java Language Specification (possibly as amended by this document). The bulk of the changes apply to the following JLS chapters:

Edits to the JLS are not presented sequentially; rather, they are organized into parts that group together related changes. Some JLS sections have multiple edits, each in a different part.

A small addendum to the Java Object Serialization Specification is made in Part E.

Changes to the Java Virtual Machine Specification, Java SE 7 Edition, are also necessary to support default methods. These changes are indicated in Part J.

Except to ensure that necessary functionality is made available by a Java Virtual Machine, this document does not consider implementation. The mapping of lambda expressions to objects, for example, is only minimally specified as required by type safety—our goal is to allow the implementer freedom as to how and when the object expressed by a lambda expression is created.

Notation

In a section tagged [New] or [Addendum], everything is new text.

In a section tagged [Modified], this is existing text, this is new text this has been removed, and this is more existing text.

The following is a formula: f(x)=z.

The following is literal program text: final int x.

This sentence introduces a new term.

This is a note containing discussion or examples. Such notes are not typically intended to appear in the revised language specification.

Summary

For the reader interested in a broad view of this document, a summary from each part is reproduced below.

Part A

A functional interface is an interface that has just one abstract method (aside from the methods of Object), and thus represents a single function contract. (In some cases, this "single" method may take the form of multiple abstract methods with override-equivalent signatures inherited from superinterfaces; in this case, the inherited methods logically represent a single method.)

In addition to the usual process of creating an interface instance by declaring and instantiating a class, instances of functional interfaces can be created with lambda expressions or method references.

The function type of a functional interface I is a method type—type parameters, formal parameter types, return types, and thrown types—that can be used to legally override the abstract method(s) of I.

The term functional interface type refers to a non-generic functional interface, a parameterization of a functional interface, a raw functional interface, or an intersection type inducing a functional interface.

Part B

A lambda expression is like a method: it provides a list of formal parameters and a body—an expression or block—expressed in terms of those parameters.

Examples of lambda expressions:

s -> s.length()

(int x, int y) -> x+y

() -> 42

(x, y, z) -> {
  if (true) return x;
  else {
    int result = y;
    for (int i = 1; i < z; i++)
      result *= i;
    return result;
  }
}

This particular syntax was chosen principally because something similar has been generally well-received in other Java-like languages (C# and Scala), and a clearly "better" alternative did not present itself. It has the advantage over alternate proposals of minimizing bracketing noise around simple lambda expressions. When some extra bracketing is needed to visually distinguish either the full lambda expression or its body expression, parentheses are naturally supported (just as in other cases in which operator precedence is unclear).

The formal parameters of a lambda expression may have either declared types or inferred types. We refer to a lambda expression whose formal parameters have declared types as explicitly-typed, and a lambda expression whose formal parameters have inferred types as implicitly-typed. The parameter types of an implicitly-typed lambda are derived from the functional interface type targeted by the expression.

A lambda body is either a single expression or a block. Like a method body, a lambda body describes code that will be executed whenever an invocation occurs.

Unlike code appearing in anonymous class declarations, the meaning of names and the this and super keywords appearing in a lambda body are the same as in the surrounding context (except that lambda parameters introduce new names).

For both lambda bodies and inner classes, local variables in the enclosing context can only be referenced if they are final or effectively final. A variable is effectively final if it is never assigned to after its initialization.

Block lambda bodies that don't return anything are considered void-compatible; block lambda bodies that return a value from every execution path are considered value-compatible. In a value-compatible lambda body, the result expressions are any expressions that may produce an invocation's value.

Part C

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.

Part D

Every expression written in the Java programming language either produces no result (void) or has a type that can be deduced at compile time. When an expression appears in most contexts, it must be compatible with a type expected in that context; this type is called the target type. For convenience, compatibility of an expression with its surrounding context is facilitated by the language in two ways:

If neither strategy is able to produce the appropriate type, an error occurs at compile time.

Given certain meanings of names, the type of a standalone expression (an expression that is not a poly expression) can be determined entirely from the contents of the expression. In contrast, the type of a poly expression may be influenced by the expression's target type.

The following forms of expressions may be poly expressions:

To determine whether an expression of one of these forms is a poly expression, we may consider the kind of context in which the expression appears and the content of the expression.

Generic method invocation expressions, along with class instance creation expressions that use a diamond <>, may be poly expressions when they appear in assignment or invocation contexts. This allows type argument inference to depend on context.

Lambda expressions and method references are always poly expressions; their typing rules are covered by Part E.

Conditional operator expressions may be poly expressions if they appear in assignment or invocation contexts, unless both operands produce primitives (or boxed primitives). When they are poly expressions, the target type is "pushed down" to each operand.

Similarly, parenthesized expressions that wrap poly subexpressions are poly expressions, passing the target type on to the subexpression.

Casts can be used to explicitly "tag" a lambda expression or a method reference with a particular target type. To provide an appropriate degree of flexibility, the target type may be a list of types denoting an intersection type (as long as the intersection is also a functional interface type, typically meaning one element is a functional interface and the others are marker interfaces). Since the feature is generally useful, we also support casts of arbitrary expressions to intersection types.

Part E

Lambda expressions and method references are always poly expressions. It is a compile-time error if one of these occurs in a program in someplace other than an assignment context, an invocation context, or a casting context.

The type of a lambda expression or method reference is a functional interface type, derived from its target type. To be compatible with the target type, the expression must be congruent with the function type of this functional interface type.

To test that a lambda expression is congruent, the function type's parameter and return types are compared to the expression. The lambda parameter types (if given) must exactly match those of the function type, while the body must be assignment-compatible with the function type's return type. The lambda's expression body (or each result expression of its block body) may be a poly expression.

To test that a method reference is congruent, a compile-time declaration is determined following the process used for method invocations. The function type's parameter types are used as argument types in this search, where the first parameter type may sometimes act as the receiver for an instance method. The selected declaration's return type is then checked to be assignment-compatible with the function type's return type.

For some method references, there is only one possible compile-time declaration with only one possible invocation type, regardless of the targeted function type. These are referred to as exact method references.

In addition to the compatibility requirement, lambda bodies and referenced methods must not throw exceptions that are incompatible with the function type's throws clause.

Evaluation of a lambda expression or method reference produces an instance of a functional interface. Evaluation does not cause the execution of a lambda body or the invocation of a referenced method; instead, this may occur at a later time when an appropriate method of the interface is invoked.

To evaluate the expression, either a new instance of an appropriate class is allocated and initialized, or an existing instance of an appropriate class is referenced. The evaluation rules are minimally restrictive, thus allowing VMs freedom for optimization. For example, a separate class need not be defined for each distinct expression, nor must a new object be allocated on every evaluation.

Part F

Method and constructor declarations can be overloaded, meaning multiple matching declarations with different parameter types can co-exist in a type. In order to interpret a method invocation or a class instance creation expression, the compiler performs "overload resolution," inferring the declaration intended by the user at a particular invocation site. This occurs in three steps: i) identifying potentially applicable methods, that is, methods of the appropriate shape; ii) performing type analysis to identify applicable methods for the given arguments; iii) among the applicable methods, choosing one that is most specific.

To accomodate lambda expressions, the definition of potential applicability is expanded to take into account both the arity of the candidate methods and the presence and "shape" of functional interface target types.

To check for applicability, the types of an invocation's arguments can no longer, in general, be inputs to the analysis. This is because:

Instead, the input to the applicability check is a list of argument expressions, which can be checked for compatibility with potential target types, even if the ultimate types of the expressions are unknown.

The meaning of an implicitly-typed lambda expression or an inexact method reference is sufficiently vague prior to resolving a target type that arguments containing these expressions are not considered pertinent to applicability; they are simply ignored (except for their expected arity) until overload resolution is finished.

The Java 7 most-specific analysis was defined as a pairwise comparison of method declarations via subtyping. Here, we augment the analysis so that, where the corresponding argument is an explicitly-typed lambda expression or an exact method reference, one functional interface type can be preferred over another if it has a "better" function type return type, by a variety of measures: subtyping, boxing, or void vs. non-void.

Part G

A variety of compile-time analyses require reasoning about types that are not yet known. Principal among these are generic method applicability testing and generic method invocation type inference. In general, we refer to the process of reasoning about unknown types as type inference.

At a high level, type inference consists of reducing compatibility assertions about expressions or types, called constraint formulas, to a set of bounds on inference variables. For example, given inference variable α, it might be determined that the constraint formula String[] <: α[] reduces to the lower bound String <: α. As bounds are inferred, they are incorporated into a bound set. Ultimately, this bound set is resolved to produce an instantiation for each of the inference variables.

To infer a generic method's applicability, we assert that the arguments to the method are compatible with their corresponding formal parameter types, and reduce these constraints to a bound set. We then check that there exists a resolution of the resulting bounds.

To infer the type of a generic method invocation, we re-use the inferred bound set from method applicability testing, augmenting it with the results of asserting the compatibility of the method's return type with its target type. If any invocation arguments are implicitly-typed lambda expressions or inexact method references, we resolve their targeted parameter types as necessary in order to allow their compatibility constraints to be safely reduced. We also assert that any exceptions thrown by lambda expression bodies are contained by the throws clauses of their target function types. After reduction, we resolve the inference variables and use them as type arguments to determine the invocation type of the method.

Type inference is also used to determine: i) a target function type for a lambda expression that is assigned to a wildcard-parameterized functional interface; and ii) whether an applicable method is more specific than another applicable, generic method.

The following details of reduction are especially noteworthy:

When a generic method invocation or diamond constructor invocation appears as the argument to another invocation, the target type of the nested invocation is the targeted formal parameter type. If the target type contains inference variables, the inference variables and bounds from the nested invocation are "lifted" into the outer inference analysis, and dependencies between the outer and inner inference variables are inferred. Ultimately, information from an outermost invocation can be "pushed down" to nested invocations via these dependencies.

When a lambda expression appears as the argument to a generic invocation, and its target type includes inference variables, we proceed by:

Thus, lambda bodies can influence the instantiation of inference variables appearing in the targeted function type's return type, and lambda parameter types, if explicit, can influence the instantiation of inference variables appearing in the targeted function type's parameter types.

A method reference appearing as the argument to a generic invocation is handled in much the same way.

Part H

A default method is a method that is declared in an interface with the modifier default. Its body provides a default implementation for any class that implements the interface without overriding the method. This allows new functionality to be added to existing (and perhaps already widely-distributed) interfaces. More generally, it provides a mechanism for multiple inheritance of behavior.

An interface may also declare static methods, which work in much the same way as static methods in classes, except that they are not inherited. Often, an interface is the most appropriate place to declare methods that produce or manipulate objects of the interface type.

An interface method that is neither default nor static is implicitly abstract.

An interface I inherits from its direct superinterfaces all abstract and default methods that are members of a superinterface, not overridden by a declaration in I, and not already overridden by another method in a superinterface of I.

Similarly, a class C inherits from its direct superclass and direct superinterfaces all abstract and default methods that are members of a supertype, not overridden by a declaration in C nor a concrete method inherited from the superclass of C, and not already overridden by another method in a supertype of C.

Notably, this implies that a method inherited from a superclass of C can override a default or abstract method in a superinterface of C. We say the superclass method overrides the superinterface method from C. In contrast, an inherited interface method never overrides any methods other than those already overridden at its declaration site.

It is a compile-time error if I or C inherits a default method whose signature is override-equivalent with another method inherited by I. This is the case whether the other method is abstract or not.

This error condition can be avoided by declaring a new method that overrides, and thus prevents the inheritance of, all conflicting methods.

An overridden default method can be accessed by using a method invocation expression of the form InterfaceName.super.m(). The named interface must be a direct superinterface of the type declaration immediately enclosing the expression.

A this expression may appear in a default method body; its type is the type of the enclosing interface. Similarly, an anonymous or local class may be declared in a default method body, so the enclosing instance of an inner class may have an interface type.

To avoid confusion with the default modifier, the access level given implicitly to unmodified declarations in classes is now referred to as package access rather than default access.

Part J

Changes to the Java Virtual Machine are necessary to support the implementation of default methods. Methods declared in interface class files need not be declared abstract, and thus can carry a Code attribute. Methods declared in interface class files may also be private or static. The invokespecial and invokestatic instructions may refer to interface methods. The rules for method resolution and invocation (via invokeinterface, invokespecial, invokestatic, and invokevirtual) are enhanced to support execution of code in interfaces.

Change Log

0.9.1

Introduction: Added brief discussions about exception transparency and speculative checking during overload resolution.

Method References: Removed the TypeName::m form of unbound method reference, which turned out to be unnecessary and introduced many complications.

Poly Expressions: Added a note clarifying that poly conditionals do not have to contain poly expressions.

Typing and Evaluation: Removed mentions of the TypeName::m method reference form. Allowed raw inner class types to be used in exact constructor references (because diamond inference cannot occur).

Overload Resolution: Eliminated unnecessary uses of the qualifier "poly" in discussions of conditional expressions.

Type Inference: Modified exception checking constraints so that they only exist for LambdaExpressions and MethodReferences (these constraints were previously generated for all other forms of expressions, and then trivially reduced to true).

Default Methods: Tweaked inheritance rule for interfaces so that a static/non-static clash would be properly detected.

Java Virtual Machine: Clarified that only 52.0 class files can allow InterfaceMethodrefs in method references of the kind invokeStatic and invokeSpecial.

0.9.0

Functional Interfaces: Introduced the term non-wildcard parameterization as an intermediate step when deriving a function type. Clarified when intersection types are used. Cleanup of some old discussion.

Lambda Expressions: Cleanup of some old discussion.

Method References: Prohibited use of constructor type arguments with diamond inference. Separated TypeName::m and ReferenceType::m as two distinct grammatical forms.

Poly Expressions: Grammatical changes so that a LambdaExpression is no longer a Primary, in order to address ambiguities.

Typing and Evaluation: Introduced the ground target type as an intermediate step towards deriving a function type. Checked that there are no overriding errors when the lambda or method reference overrides the methods of this type. Described exactly which methods are overridden, and which (erasure-based) casts occur at runtime. Accommodated the additional TypeName::m syntactic form of a method reference. Described how references to signature-polymorphic methods are handled. Added new changes to 13.1 to account for method references.

Overload Resolution: Asserted that, for a more-specific test of two functional interfaces targeted by an exact method references, the parameter types are the same. Cleaned up the rules for deriving the actual target types of invocation arguments when unchecked conversion was necessary.

Type Inference: Mirrored the changes in Parts E and F. Clarified how inference variables in a wildcard-parameterized target type of an explicitly-typed lambda expression are handled, and cleaned up the section describing functional interface parameterization inference. Clarified how subtyping and equality constraints handle non-parameterized inner classes of parameterized types. Added an incorporation rule to check consistency of parameterized upper bounds. Cleaned up the treatment of ? extends Object, which should be equivalent to ?. Added some overlooked resolution dependencies on capture inference variables. Added rules to invocation type inference to special-case when the return type is an inference variable, and may end up either being wildcard-parameterized or requiring unchecked conversion. Explicitly moved the definition of lub to 4.10.4.

Default Methods: Prohibited invoking a static interface method with an expression qualifier.

0.8.0

Poly Expressions: Prohibited arrays in intersection casts.

Typing and Evaluation: Made lambdas incompatible with generic targeted function types. Performed capture before the method reference method search. Avoided diamond inference for inner classes of raw types. Defined method references requiring inference as inexact. Specified unchecked warnings for method reference assignment. Added lambdas and method references to 15.7.5.

Overload Resolution: Clarified the invocation type of the getClass method. Clarified that unchecked invocation does not cause target parameter types to be erased.

Type Inference: No longer require a bound set as input to reduction. Allowed narrowing of primitive constants in lambda bodies. Clarified when unchecked conversion occurs during inference. Cleaned up reduction of containment/equality constraints involving wildcards. Fixed minor notational problems.

Default Methods: Added the runtime behavior of default method invocation (15.12.4.4). Defined concrete methods. Updated the definition of hiding (by static methods), consistent with previous changes to overriding. Clarified that TypeName.super cannot be used to refer to a type variable. Clarified that the type to search, for InterfaceName.super, is provided by the implements clause.

Java Virtual Machine: Allowed invokeStatic and invokeSpecial MethodHandles to use InterfaceMethodrefs. Prohibited static and non-public methods of class Object from being the resolution of an InterfaceMethodref.

0.7.0

Typing and Evaluation: Added a paragraph for the Java Object Serialization Specification. Cleaned up presentation of method reference resolution logic.

Overload Resolution: Ensured that, in most-specific testing, all varargs parameter types are considered, even when there are 0 varargs arguments.

Type Inference: Provided full rules for "more specific method" inference. Backed off of approach to unchecked conversion inference, and specified when unchecked conversions are allowed by reduction. In resolution, adjusted to perform lub only on proper types.

Default Methods: Added a discussion about binary compatibility to Chapter 13.

Java Virtual Machine: Fixed text in method resolution to properly ignore static and private methods in superinterfaces.

0.6.3

Functional Interfaces: Renamed the term function descriptor to function type (undoing the previous renaming of functional interface type to function type). Cleaned up the conditions under which an intersection type can be considered a functional interface type. Addressed a negative interaction of wildcards with derivation of a function type.

Lambda Expressions: Introduced the terms explicitly-typed lambda and implicitly-typed lambda. Changed treatment of "_" to allow it as a name in non-lambda contexts (noting the possibility of future deprecation).

Typing and Evaluation: Introduced the terms exact method reference and inexact method reference. Removed the compatibility condition for lambda expressions that their body not contain errors. Introduced a section detailing the process of identifying a compile-time declaration for a method reference (distinct from testing for compatibility). Adjusted resolution of an unbound/static method reference to be less brittle.

Overload Resolution: Asserted that arguments involving implicitly-typed lambdas and inexact method references are not pertinent to applicability; they are only checked for arity during overload resolution. (This replaces the approach of considering some methods to be only provisionally applicable.) Minimized the changes to most-specific analysis, so that extra (non-subtyping) work is only done when two functional interfaces are compared and correspond to an explicitly-typed lambda or an exact method reference. Adjusted potential applicability of an unbound/static method reference to be less brittle. Made the accessibility of a varargs type a post-resolution check.

Type Inference: Added new bounds to represent capture variables and variables that appear in throws clauses, and described their impact on incorporation and resolution. Eliminated the notion of "delayed constraints". Defined special reduction rules for exact method references. Described reduction of throws constraints. Described how invocation type inference handles sequencing of reduction for constraints on arguments that are not pertinent to applicability, as well as throws constraints (interleaved with resolution of variables, as needed). Made use of capture bounds during invocation type inference.

Default Methods: Prohibited static and default methods from the body of annotation type declarations (@interfaces).

Java Virtual Machine: Introduced the term maximally-specific superinterface methods for use in resolution and selection. Adjusted resolution to be more flexible and to ignore static and private methods in superinterfaces. Prohibited invokespecial from referring to indirect superinterfaces. Cleaned up the selection logic of invokespecial. Clarified how the changes affect older class files. Adjusted definition of overriding to be consistent with actual behavior in VMs.

0.6.2

Functional Interfaces: Renamed the term functional interface type to just function type, to avoid the assumption that intersection types are excluded from this set. Defined the descriptor of a raw functional interface type. Minor fixes in examples to reflect actual compiler behavior. Adjusted the definition of return-type substitutability to reflect actual compiler behavior.

Lambda Expressions: Small change to the scoping rules of local classes to avoid confusion.

Method References: Added a number of well-formedness checks for method references (some new, some previously covered by the compatibility definition). Adjusted terminology so that "method references" refers generally to both "constructor references" and "array creation references".

Poly Expressions: Incorporated above terminology changes. Added section 15.29, which is just a renumbering of 15.28.

Typing and Evaluation: Added a lambda compatibility rule that errors do not occur in the lambda body. Made the check for static-ness of a referenced method a post-compatibility error. Removed mention of "synthetic" classes and methods, to clarify that the ACC_SYNTHETIC flag is not mandated. Unified the presentation of "compile-time declarations"/runtime behavior for standard method references, constructor references, and array creation references—the latter two are based on "notional methods" that represent class instance creation or array creation. Moved the error check for exceptions in lambda bodies to 11.2.3.

Overload Resolution: Changed definition of "potentially compatible" for method references to exclude cases in which there are no method declarations of the desired arity. Defined provisionally-applicable methods to never be more specific rather than always more specific (the outcome should be the same, though). Unified the presentation of "more specific" for fixed-arity and variable-arity methods.

Type Inference: Specified reduction for subtyping and equality constraints. Specified incorporation. Specified resolution. Updated reduction rules for lambdas and method references to track changes in "Typing and Evaluation." Adjusted terminology so that "bound" refers to all of "proper bounds", "dependencies", and "delayed constraint formulas". Made tweaks to the notation for constraint formulas and bounds.

Default Methods: Removed support for an explicit package access modifier. Refined the definition of overriding to more accurately represent the intended behavior when the overriding method is inherited (mostly to account for package-access methods).

Java Virtual Machine: Changed the representation of methods declared in interfaces and passed to invokespecial/invokestatic from a Methodref to an InterfaceMethodref. Rolled back changes that were intended to support Methodref structures that point to methods declared in interfaces.

0.6.1

Functional Interfaces: Renamed the @Functional annotation to @FunctionalInterface.

Typing and Evaluation: Clarified the unpredictable semantics of operators like == when applied to the value produced by a lambda expression or method reference.

Type Inference: Described enhanced analysis for nested generic method invocations, which involves additional forms of dependencies. Described delayed constraints and defined the conditions under which they are produced by lambda expressions and method references. As a simplification, eliminated context type from the compatibility constraint formulas. Defined reduction for poly conditional expressions. Revised inference process for instantiating wildcard-parameterized functional interface targets.

Default Methods: Eliminated support for synchronized methods in interfaces.

Java Virtual Machine: Adjusted the definition of Methodref_info to allow for methods in interfaces. Adjusted restrictions on modifiers for interface methods. Revised resolution rules and specification for invokevirtual. Introduced adjustments to invokespecial and invokestatic to support interface methods.

0.6.0

Overall: Split Part F into Part F, Overload Resolution and Part G, Type Inference. Split the old Part G into Part H, Default Methods and Part J, Java Virtual Machine.

Functional Interfaces: Defined intersections as a kind of functional interface type. Defined the descriptor of wildcard-parameterized types. Added the @Functional annotation.

Lambda Expressions: Added the _ keyword and the -> operator to the grammar.

Method References: Added qualified super references. Added array constructor references. Added the :: separator to the grammar.

Poly Expressions: Allowed casts to intersection types. Refined the conditions under which a method invocation is considered a poly expression. Introduced rules for classifying and typing conditional expressions.

Typing and Evaluation: Refined the presentation of inference of wildcard-parameterized type instantiations. Allowed arbitrary statement expressions in lambda bodies targeting a void return. Always interpret lambda returns in an assignment context. Defined runtime behavior when targeting an intersection functional interface type. Eliminated support for unbound inner class constructor references. Added support for qualified super references and array constructor references. Restricted supported forms of static method references.

Overload Resolution: Defined potentially applicable for methods with functional interface parameter types targeted by lambda expressions. Revised most specific method analysis to consider the invocation argument expressions, compare descriptors of functional interface types, and minimize boxing/unboxing.

Type Inference: Added a stub for most specific method inference.

Default Methods: Modified syntax, treating default as a method modifier. Added support for static interface methods. Refined the inheritance rules for default and abstract methods. Enclosing instances of inner classes can be interfaces. Added support for the package access modifier.

0.5.1

Introduction: Revised and added to the discussion of future enhancements.

Lambda Expressions: To allow void method invocations as expression lambda bodies, restricted the void-/value-compatible distinction to block bodies. Refined the definition of effectively final to conform with the JLS 7 bug fixes to the rules for final variables. Added a note in the section on this that lambda expressions do not introduce a new this scope.

Method and Constructor References: Added super method references.

Typing and Evaluation: Adjusted lambda compatibility rules to support void method invocations as lambda expression bodies. Adjusted method reference compatibility rules to support super method references. Clarified that class type arguments in a constructor reference can be inferred. Described the details of method and constructor reference evaluation, in particular how the reference is interpreted as an invocation.

Type Inference: Updated lambda compatibility inference rules consistent with the changes to support void method invocations. Added examples and discussion.

Default Methods: Allowed this to appear in the body of a default method. Added discussion on super method invocations.

0.5.0

Overall: Introduced the above "Summary" section, providing a digestible review of the contents of each part. Formatted to support each part as a separate HTML document. Added the above "Unfinished Items" section, and removed most other design discussions that speculated on future changes. These enhancement ideas are recorded and discussed elsewhere, leaving the spec document to act as a more stable baseline. Minor rephrasing and presentation cleanup throughout.

Functional Interfaces: Backed out of a flawed attempt to rewrite 8.4.6 in a way that minimized the use of erasure.

Lambda Expressions: Eliminated syntax supporting generic lambda expressions, which was intrusive. Settled on a strategy in which generic functional interfaces are supported, but cannot be instantiated by lambda expressions; they can still be instantiated by method references. Removed support for recursive lambdas and associated changes to the definite assignment rules. Removed orphaned discussion of Void as a return type (the related feature was already removed in 0.4.2). Updated rules about lambda parameters to mimic 8.4.1 in JLS 7. Updated rules about scope and shadowing to match changes in JLS 7, which handles all these rules in 6.3 and 6.4. Added lambda parameters to 4.12.3.

Poly Expressions: Merged the previous "Conversions and Contexts" part with the first half of the previous "Poly Expressions". This part now includes all discussion about contexts and poly expressions, except for the compatibility and typing rules for lambdas and method references. Updated 5.4 to match changes in JLS 7. Eliminated special grammar rules for handling generic lambda expressions.

Typing and Evaluation: Merged the second half of the previous "Poly Expressions" part with new material on lambda expression and method reference evaluation. Improved the compatibility definitions and clarified their interface with type inference in the case in which the target type has wildcards.

Type Inference: Added this part.

Default Methods: Added this part.

0.4.2

Lambda Expressions: Removed rules that support treatment of void lambda bodies as implementations of methods that return Void; expanded the accompanying discussion about the possible approaches.

Poly Expressions: Removed compatibility rules allowing void lambda bodies or method references in contexts that require a Void return type.

0.4.1

Functional Interfaces: Allowed generic methods, and added corresponding examples. Revised "return type substitutable" and related tests to take into account alpha-equivalent type parameters.

Lambda Expressions: Updated the syntax to the C#/Scala style. Added syntax for and a section addressing lambda type parameters. Further discussion about parsing. Renumbered to section 15.27. Prohibited shadowing with lambda parameters. Allowed local classes to capture effectively-final variables.

Method and Constructor References: Updated the syntax (noting that it is still subject to change). Added discussion about parsing. Renumbered to section 15.28.

Conversions and Contexts: Swapped the order with "Poly Expressions" (making this Part D) and moved the material about expression compatibility rules into the Poly Expressions part (now Part E). Revised introductory discussion to explicitly define "target type" and clarify that poly expressions and implicit conversions are different, complementary features. De-emphasized the "compatibility" terminology, eliminating the need for many of the modifications in previous versions. Reverted section numbers to those in the JLS.

Poly Expressions: Eliminated the PolyExpression grammar production; lambda expressions and method references as syntactically primaries, and appropriate context is checked as a semantic rather than syntactic restriction. Added grammar rules to prevent generic lambdas after casts. Revised some section numbering, introducing a general discussion of expressions and poly expressions in 15.2. Eliminated the poly context terminology, relying instead on the existing context concepts from Chapter 5. Stopped designating constant expressions as poly expressions, instead relying on the old conversion semantics for implicit constant narrowing. Revised method reference search to allow instance method references to get the receiver's type parameters from the target type.

Appendix: Eliminated the need for changes to the grammar throughout the JLS that made up the bulk of the former appendix.

0.4.0

Overall: Reformatted as HTML with extensive links.

Functional Interfaces: Renamed "SAM types"; redefined this property in terms of declarations rather than type instantiations. Eliminated a dependency on the particulars of return-type-substitutability. Ensured that the interface can be generically overridden, but avoided attempts to make guarantees about type instantiations.

Lambda Expressions: Updated discussion on syntax.

Conversions and Contexts: Added note about making method reference parameter type compatibility more strict in strict invocation contexts.

0.3.5

Overall: Promoted the "to discuss" section to a summary of unresolved questions in the document. Added Part C, Method References (subsequent parts were renamed). Added an appendix, Part Z, to hold negligible changes that are distracting in the main body of the text. Added discussion of potential future enhancements at the end of the document.

SAM Types: Adjusted the definition of "SAM type" for wildcard-parameterized types to use capture; made the corresponding descriptor undefined. Adjusted the criteria under which an Object method is disregarded. Added a check that some abstract method of a SAM type is return-type-substitutable for all others (not guaranteed when type arguments are applied). Added more examples involving generic SAM types. Altered the return-type-substitutable definition to more closely match implementations' behavior.

Lambda Expressions: Added more discussion about syntax alternatives. Moved Void return description in 14.2 to Part F. Extended discussion about the possibility of return type boxing via overriding and bridge methods. Noted that the handling of shadowing rules is incomplete.

Poly Expressions: Added method references as an additional kind of poly expression. Added discussion about chained inference. Moved many grammar production renamings into the appendix.

Conversions and Contexts: Moved some of the adjustments to the casting conversion text into the appendix. Revised compatibility rules for lambda expressions. Introduced compatibility rules for method references.

0.3.4

Introduction: Added a reference list of optional non-lambda changes that should be discussed. Added Part E, Lambda Expression Evaluation.

SAM Types: Added examples and discussion involving generic interfaces. Added more examples of SAM descriptor thrown types.

Lambda Expressions: Made effectively final references from inner classes an optional revision (moving it into discussion). Also made implicit returns to Void in method bodies optional, and specified handling of returns to Void when the body completes normally. Moved the effectively final definition into 4.12.4. Adjusted the restriction on break and continue labels to better integrate with existing text.

0.3.3

SAM Types: Removed support for SAM class types. Moved the specification to Chapter 9 (Interfaces). Clarified the definition of SAM type. Restricted the set of abstract methods that "don't count" in interfaces to the methods of Object that are defined to be implicit members (9.2). Improved SAM type examples. Simplified SAM descriptor definition and eliminated any use of order of methods (see discussion). Added discussion about accessibility. Added discussion about additional considerations if abstract classes were allowed.

Lambda Expressions: Made "final" and "effectively final" mutually exclusive. Clarified the discussion about meaning of names and dependencies on type checking. Prohibited mixing value and void returns in a method. Added new changes for sections 9.3.1 and 12.5. Deferred treatment of the interaction between SAM types and lambdas to later sections.

0.3.2

SAM Types: Added discussion about method order and about generic methods. Added SAM descriptor examples. Small additional comments and cleanup.

Potential Future Enhancements

The following have been determined to be outside the scope of JSR 335. While there are no concrete plans to do so, it is possible that they might be considered as enhancements to the JSR 335 features in a future iteration of the Java Programming Language.

Functional Classes

It would be possible to treat certain abstract classes that have a single abstract method as lambda expression targets, like functional interfaces. Good examples from the Java SE API are java.util.TimerTask, javax.swing.InputVerifier, javax.swing.SwingWorker, and javax.swing.AbstractAction.

This is best handled in the current framework by creating a subclass with a constructor that takes a functional interface—the Thread(Runnable) constructor essentially does this, although it is not designed very cleanly. Arguably, the strategy of delegating to a functional-interface-typed field rather than an abstract method ought to be the preferred approach when new APIs are developed, and so there would be much less need to declare functional classes. (On the other hand, anonymous inner classes that implement abstract methods have more convenient access to the members of the superclass.)

The biggest reason that functional classes have been avoided is that defining a synthetic class that extends an arbitrary class is much more difficult and constraining than defining a synthetic class that implements an arbitrary interface: the superclass may have an enclosing instance; the superclass constructor may have parameters; the superclass may have inaccessible abstract methods or constructors. Most significantly, the superclass constructor can execute arbitrary code and throw arbitrary (possibly even checked) exceptions. This conflicts with our design goal of allowing implementations freedom regarding when and how often instances of these synthetic classes are created.

Standalone Lambda Expressions & Structural Function Types

In contexts that do not provide a target type, it would be possible to treat the value of a lambda expression as a special object with a structural function type. Such values could later be applied directly, converted to functional interface instances, or, if structural function types are denotable, assigned to a variable.

Structural function types are difficult for users because they introduce a new category of structural type syntax that everyone has to understand. If the types are erased, their usefulness is limited by clashes that arise when declaring overloaded methods. Structural function types are difficult for the specification and implementation because the entire type system has to be adjusted to take into account the existence of a new kind of type.

Nonlocal Control Flow

The body of a lambda expressions is evaluated as an expression (as a method invocation, to be precise), meaning that ultimately the evaluation either completes—possibly producing a value—or throws an exception.

There are many interesting applications that involve evaluating a lambda-like abstraction as a statement. This would allow evaluation of the body to have other effects, such as returning (rather than producing) a value or breaking out of a loop. See 14.1 for the comprehensive list of possible effects of statement execution. These effects, when triggered by evaluation of a lambda-like abstraction, can be termed "nonlocal," because the code that describes them appears in a different location than the code that triggers them. As an example, a for loop could be re-expressed as a call to a library method that takes as input a lambda-like abstraction; the body of the library method invokes its input as a statement, and the effects of doing so may cause the library method to terminate.

This is a more ambitious and less well-understood problem domain than the approach we take of evaluating lambda bodies as method invocations. It is a less-natural fit for the existing language.

Capture of Mutable Variables

Lambda expressions can only refer to local variables and parameters from the surrounding scope if those variables are effectively final, meaning that their values never change. This allows the variable to be "captured" for later use as a value rather than a variable.

It might seem awkward to be unable to, say, keep a tally of the number of times a lambda body is invoked by incrementing a local variable. However, if different threads invoke the body at the same time, it is very easy for concurrency bugs to manifest themselves. To responsibly facilitate that kind of behavior in the language, we would prefer to provide some sort of static analysis that helps to prevent concurrency bugs.

On the other hand, a safer and cleaner approach to solving problems like this is to avoid mutation of shared variables. The current language restrictions encourage those kinds of solutions.

Special Exception Checking for Lambda Body Invocations

A checked exception thrown by a lambda body should be identified by the type system wherever the corresponding method is invoked. This is supported in a limited way by allowing functional interface methods to have throws clauses—then, naturally, the method invocation knows what exceptions may be thrown. It is also possible to use a type parameter of a functional interface in the throws clause, thus allowing a thrown exception type to be inferred (by, say, the invocation of a library method that accepts a lambda argument).

However, generics are not well-suited to the problem of representing the exceptions thrown by a block of code. In the common case (zero checked exceptions), an extra type parameter is a painful clerical burden (for example, Function<String, Number> becomes Function<String, Number, RuntimeException>). And in cases in which multiple exceptions are thrown, there is no way to provide a list of types as a type argument. Even with workarounds for these problems, it is difficult to write lambda-friendly library code that properly accounts for all the exception types thrown by the provided lambda bodies.

A more ambitious solution would be to special-case the treatment of lambdas in the compiler's exception checking logic, detecting the locations in which the checked exceptions of a lambda body may manifest themselves without relying on the throws clause of the functional interface. This would eliminate any clerical burden on programmers, while still providing strong exception checking; but it would require the compiler to perform advanced analysis techniques.

Speculative Type Checking During Overload Resolution

Implicitly-typed lambda expressions (that is, lambdas with parameters that do not declare their types) and inexact method references (that is, references to overloaded or generic methods) cannot be type-checked before their parameter types are known. These types are derived from the targeted functional interface type. In the case of a method invocation argument (e.g., m(x -> x.foo())), if the method being invoked is overloaded, there may be multiple possible target types, one for each overloaded method declaration.

The approach developed here is to ignore the lambda expression or method reference until after overload resolution decides on the method to be invoked—the lambda argument is not pertinent to applicability. Once overload resolution completes, the lambda body can be type-checked.

Another possible approach is to type-check the lambda body or method reference speculatively, once for each possible target type. This provides a more powerful disambiguation mechanism for overload resolution—the use of lambda parameters in the lambda body may clarify which parameter type was expected. However, there are a number of challenges: users must consider multiple possible typings when reading a block of code; program behavior depends on subtle type errors; worst-case computational complexity is exponential. And in some cases, it is still necessary to ignore lambda expressions during overload resolution, because the parameter types are inferred from the method invocation's own target type.

Legal Notice

Copyright © 2013 Oracle America, Inc.
4150 Network Circle, Santa Clara, California 95054, U.S.A. All rights reserved.

NOTICE

The Specification is protected by copyright and the information described therein may be protected by one or more U.S. patents, foreign patents, or pending applications. Except as provided under the following license, no part of the Specification may be reproduced in any form by any means without the prior written authorization of Oracle USA, Inc. ("Oracle") and its licensors, if any. Any use of the Specification and the information described therein will be governed by the terms and conditions of this Agreement.

Subject to the terms and conditions of this license, including your compliance with Paragraphs 1 and 2 below, Oracle hereby grants you a fully-paid, non-exclusive, non- transferable, limited license (without the right to sublicense) under Oracle's intellectual property rights to:

1. Review the Specification for the purposes of evaluation. This includes: (i) developing implementations of the Specification for your internal, non-commercial use; (ii) discussing the Specification with any third party; and (iii) excerpting brief portions of the Specification in oral or written communications which discuss the Specification provided that such excerpts do not in the aggregate constitute a significant portion of the Technology.

2. Distribute implementations of the Specification to third parties for their testing and evaluation use, provided that any such implementation:

(i) does not modify, subset, superset or otherwise extend the Licensor Name Space, or include any public or protected packages, classes, Java interfaces, fields or methods within the Licensor Name Space other than those required/authorized by the Specification or Specifications being implemented;

(ii) is clearly and prominently marked with the word "UNTESTED" or "EARLY ACCESS" or "INCOMPATIBLE" or "UNSTABLE" or "BETA" in any list of available builds and in proximity to every link initiating its download, where the list or link is under Licensee's control; and

(iii) includes the following notice: "This is an implementation of an early-draft specification developed under the Java Community Process (JCP) and is made available for testing and evaluation purposes only. The code is not compatible with any specification of the JCP."

The grant set forth above concerning your distribution of implementations of the specification is contingent upon your agreement to terminate development and distribution of your "early draft" implementation as soon as feasible following final completion of the specification. If you fail to do so, the foregoing grant shall be considered null and void.

No provision of this Agreement shall be understood to restrict your ability to make and distribute to third parties applications written to the Specification.

Other than this limited license, you acquire no right, title or interest in or to the Specification or any other Oracle intellectual property, and the Specification may only be used in accordance with the license terms set forth herein. This license will expire on the earlier of: (a) two (2) years from the date of Release listed above; (b) the date on which the final version of the Specification is publicly released; or (c) the date on which the Java Specification Request (JSR) to which the Specification corresponds is withdrawn. In addition, this license will terminate immediately without notice from Oracle if you fail to comply with any provision of this license. Upon termination, you must cease use of or destroy the Specification.

"Licensor Name Space" means the public class or interface declarations whose names begin with "java", "javax", "com.oracle" or their equivalents in any subsequent naming convention adopted by Oracle through the Java Community Process, or any recognized successors or replacements thereof.

TRADEMARKS

No right, title, or interest in or to any trademarks, service marks, or trade names of Oracle or Oracle's licensors is granted hereunder. Oracle, the Oracle logo, Java are trademarks or registered trademarks of Oracle USA, Inc. in the U.S. and other countries.

DISCLAIMER OF WARRANTIES

THE SPECIFICATION IS PROVIDED "AS IS" AND IS EXPERIMENTAL AND MAY CONTAIN DEFECTS OR DEFICIENCIES WHICH CANNOT OR WILL NOT BE CORRECTED BY ORACLE. ORACLE MAKES NO REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT THAT THE CONTENTS OF THE SPECIFICATION ARE SUITABLE FOR ANY PURPOSE OR THAT ANY PRACTICE OR IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADE SECRETS OR OTHER RIGHTS. This document does not represent any commitment to release or implement any portion of the Specification in any product.

THE SPECIFICATION COULD INCLUDE TECHNICAL INACCURACIES OR TYPOGRAPHICAL ERRORS. CHANGES ARE PERIODICALLY ADDED TO THE INFORMATION THEREIN; THESE CHANGES WILL BE INCORPORATED INTO NEW VERSIONS OF THE SPECIFICATION, IF ANY. ORACLE MAY MAKE IMPROVEMENTS AND/OR CHANGES TO THE PRODUCT(S) AND/OR THE PROGRAM(S) DESCRIBED IN THE SPECIFICATION AT ANY TIME. Any use of such changes in the Specification will be governed by the then-current license for the applicable version of the Specification.

LIMITATION OF LIABILITY

TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT WILL ORACLE OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES, INCLUDING WITHOUT LIMITATION, LOST REVENUE, PROFITS OR DATA, OR FOR SPECIAL, INDIRECT, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF OR RELATED TO ANY FURNISHING, PRACTICING, MODIFYING OR ANY USE OF THE SPECIFICATION, EVEN IF ORACLE AND/OR ITS LICENSORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

You will hold Oracle (and its licensors) harmless from any claims based on your use of the Specification for any purposes other than the limited right of evaluation as described above, and from any claims that later versions or releases of any Specification furnished to you are incompatible with the Specification provided to you under this license.

RESTRICTED RIGHTS LEGEND

If this Software is being acquired by or on behalf of the U.S. Government or by a U.S. Government prime contractor or subcontractor (at any tier), then the Government's rights in the Software and accompanying documentation shall be only as set forth in this license; this is in accordance with 48 C.F.R. 227.7201 through 227.7202-4 (for Department of Defense (DoD) acquisitions) and with 48 C.F.R. 2.101 and 12.212 (for non-DoD acquisitions).

REPORT

You may wish to report any ambiguities, inconsistencies or inaccuracies you may find in connection with your evaluation of the Specification ("Feedback"). To the extent that you provide Oracle with any Feedback, you hereby: (i) agree that such Feedback is provided on a non-proprietary and non-confidential basis, and (ii) grant Oracle a perpetual, non-exclusive, worldwide, fully paid-up, irrevocable license, with the right to sublicense through multiple levels of sublicensees, to incorporate, disclose, and use without limitation the Feedback for any purpose related to the Specification and future versions, implementations, and test suites thereof.

GENERAL TERMS

Any action related to this Agreement will be governed by California law and controlling U.S. federal law. The U.N. Convention for the International Sale of Goods and the choice of law rules of any jurisdiction will not apply.

The Specification is subject to U.S. export control laws and may be subject to export or import regulations in other countries. Licensee agrees to comply strictly with all such laws and regulations and acknowledges that it has the responsibility to obtain such licenses to export, re-export or import as may be required after delivery to Licensee.

This Agreement is the parties' entire agreement relating to its subject matter. It supersedes all prior or contemporaneous oral or written communications, proposals, conditions, representations and warranties and prevails over any conflicting or additional terms of any quote, order, acknowledgment, or other communication between the parties relating to its subject matter during the term of this Agreement. No modification to this Agreement will be binding, unless in writing and signed by an authorized representative of each party.