7/18/2014 Trying Out Lambda Expressions in the Eclipse IDE http://www.oracle.com/technetwork/articles/java/lambda-1984522.html 1/22 Application Development Framew ork Application Express Big Data Business Intelligence Cloud Computing Communications Database Performance & Availability Data Warehousing Database .NET Dynamic Scripting Languages Embedded Digital Experience Enterprise Architecture Enterprise Management Identity & Security Java Linux Service-Oriented Architecture Solaris SQL & PL/SQL Systems - All Articles Virtualization Trying Out Lambda Expressions in the Eclipse IDE by Deepak Vohra Learn how to make the best of lambdas and virtual extension methods. Published August 2013 Lambda expressions, also called closures, are a short-form replacement for anonymous classes. Lambda expressions simplify the use of interfaces that declare a single abstract method, which are also called functional interfaces. In Java SE 7, a single method interface can be implemented with one of the following options. Create a class that implements the interface. Create an anonymous class. A lambda expression can be used to implement a functional interface without creating a class or an anonymous class. Lambda expressions can be used only with interfaces that declare a single method. Lambda expressions are designed to support a multicore processor architecture, which relies on software that provides parallelism, which in turn, improves performance and reduces completion time. Benefits of lambda expressions include the following: Concise syntax Method references and constructor references Reduced runtime overhead compared to anonymous classes Prerequisites To follow along with the examples in this article, download and install the following software: JDK 8 Eclipse IDE with JDK 8 support Syntax of Lambda Expressions The syntax of a lambda expression is as follows. (formal parameter list) ->{ expression or statements } The parameter list is a comma-separated list of formal parameters that match the formal parameters of the single method in a functional interface. Specifying the parameter types is optional; if the parameter types are not specified, the types are inferred from the context. The parameter list must be enclosed in within parentheses except when a single parameter is specified without the parameter type; a single formal parameter can be specified without parentheses. If a functional interface method does not specify any formal parameters, empty parentheses must be specified. The parameter list is followed by the -> operator, which is followed by the lambda body, which is a single expression or a statement block. The lambda body has a result that must be one of the following: void , if the functional interface method result is void A Java type, primitive type, or reference type that is the same as the return type of the functional interface method The lambda body result is returned according to one of the following options: If a single expression is used as the lambda body, the expression value is returned. If the method has a return type and the lambda body is not a single expression, the lambda body must return a value using a return statement. If the functional interface method result is void , a return statement can be provided, but that is not required. A statement block must be enclosed within curly braces ({} ) unless the statement block is a method invocation statement for a method whose result is void . The lambda body result must be the same as the result of the single method in the functional interface. For example, if the functional interface method result is void , the lambda expression body must not return a value. If the functional interface method has a return type of String , the lambda expression body must return a String . If the lambda body is a single statement and the method has a return type, the statement must be a return statement. When a lambda expression is invoked, the code in the lambda body is run. Functional Interfaces A lambda expression is used with a functional interface, which is an interface with essentially one abstract method; the interface can contain a method that is also included in the Object class. Some examples of functional interfaces are java.util.concurrent.Callable —which has a single method, call() —and java.lang.Runnable —which has a single method, run() . As a comparison, an anonymous class for an interface involves specifying an instance creation expression for the interface and the compiler creating an instance of a class that implements the interface. Unlike an anonymous class, which specifies the interface type (or class type), a lambda expression does not specify the interface type. The functional interface for which a lambda expression is invoked, also called the target type of a lambda expression, is inferred from the context. Target Type of a Lambda Expression A lambda expression has an implicit target type associated with it because an interface type is not explicitly specified. In a lambda expression, the target type of a lambda conversion must be a functional interface. The target type is inferred from the context. Therefore, lambda expressions can be used only in contexts in which the target type can be inferred. Such contexts are A variable declaration An assignment A return statement An array initializer Method or constructor arguments A lambda expression body A ternary conditional expression Oracle Technology Network Articles Java Products Solutions Downloads Store Support Training Partners About OTN Sign In/Register Help Country Communities I am a... I want to... Search
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
7/18/2014 Trying Out Lambda Expressions in the Eclipse IDE
Trying Out Lambda Expressions in the Eclipse IDEby Deepak Vohra
Learn how to make the best of lambdas and virtual extension methods.
Published August 2013
Lambda expressions, also called closures, are a short-form replacement for anonymous classes. Lambda expressions simplify the use of
interfaces that declare a single abstract method, which are also called functional interfaces. In Java SE 7, a single method interface can be
implemented with one of the following options.
Create a class that implements the interface.Create an anonymous class.A lambda expression can be used to implement a functional interface without creating a class or an anonymous class. Lambda expressions can
be used only with interfaces that declare a single method.
Lambda expressions are designed to support a multicore processor architecture, which relies on software that provides parallelism, which in
turn, improves performance and reduces completion time.
Benefits of lambda expressions include the following:
Concise syntaxMethod references and constructor referencesReduced runtime overhead compared to anonymous classes
PrerequisitesTo follow along with the examples in this article, download and install the following software:
JDK 8Eclipse IDE with JDK 8 support
Syntax of Lambda ExpressionsThe syntax of a lambda expression is as follows.
(formal parameter list) ->{ expression or statements }
The parameter list is a comma-separated list of formal parameters that match the formal parameters of the single method in a functional
interface. Specifying the parameter types is optional; if the parameter types are not specified, the types are inferred from the context.
The parameter list must be enclosed in within parentheses except when a single parameter is specified without the parameter type; a single
formal parameter can be specified without parentheses. If a functional interface method does not specify any formal parameters, empty
parentheses must be specified.
The parameter list is followed by the -> operator, which is followed by the lambda body, which is a single expression or a statement block. The
lambda body has a result that must be one of the following:
void, if the functional interface method result is voidA Java type, primitive type, or reference type that is the same as the return type of the functional interface methodThe lambda body result is returned according to one of the following options:
If a single expression is used as the lambda body, the expression value is returned.If the method has a return type and the lambda body is not a single expression, the lambda body must return a value using a return statement.If the functional interface method result is void, a return statement can be provided, but that is not required.A statement block must be enclosed within curly braces ({}) unless the statement block is a method invocation statement for a method whose
result is void. The lambda body result must be the same as the result of the single method in the functional interface. For example, if the
functional interface method result is void, the lambda expression body must not return a value. If the functional interface method has a return type
of String, the lambda expression body must return a String. If the lambda body is a single statement and the method has a return type, the
statement must be a return statement. When a lambda expression is invoked, the code in the lambda body is run.
Functional InterfacesA lambda expression is used with a functional interface, which is an interface with essentially one abstract method; the interface can contain a
method that is also included in the Object class. Some examples of functional interfaces are java.util.concurrent.Callable—which has a
single method, call()—and java.lang.Runnable—which has a single method, run().
As a comparison, an anonymous class for an interface involves specifying an instance creation expression for the interface and the compiler
creating an instance of a class that implements the interface. Unlike an anonymous class, which specifies the interface type (or class type), a
lambda expression does not specify the interface type. The functional interface for which a lambda expression is invoked, also called the target
type of a lambda expression, is inferred from the context.
Target Type of a Lambda ExpressionA lambda expression has an implicit target type associated with it because an interface type is not explicitly specified. In a lambda expression, the
target type of a lambda conversion must be a functional interface. The target type is inferred from the context. Therefore, lambda expressions can
be used only in contexts in which the target type can be inferred. Such contexts are
A variable declarationAn assignmentA return statementAn array initializerMethod or constructor argumentsA lambda expression bodyA ternary conditional expression
Oracle Technology Network Articles Java
Products Solutions Downloads Store Support Training Partners About OTN
Sign In/Register Help Country Communities I am a... I want to... Search
Using the Eclipse IDE with Java SE 8 SupportTo use Java 8 in the Eclipse IDE, you need to download an Eclipse version that supports JDK 8.
In Eclipse, select Windows > Preferences and then select Java > Installed JREs. Install a JRE for JDK 8 using the JDK 8 you downloaded in the"Prerequisites" section.Select Java > Compiler and set Compiler compliance level to 1.8, as shown in Figure 1.
Figure 1
Click Apply and then OK.Select the JDK 1.8 JRE when creating a Java project in Eclipse.
Next, we discuss how lambda expressions can be used by looking at some examples.
The Hello Application with Lambda ExpressionsWe are familiar with the Hello application that outputs a message when supplied with a name. Class Hello declares two fields, two
constructors, and a hello() method to output a message, as shown below.
public class Hello { String firstname; String lastname; public Hello() {} public Hello(String firstname, String lastname) { this.firstname = firstname; this.lastname = lastname;} public void hello() { System.out.println("Hello " + firstname + " " + lastname);} public static void main(String[] args) { Hello hello = new Hello(args[0], args[1]); hello.hello(); }}
Now, we will see how lambda expressions simplify the syntax in the Hello example. First, we need to create a functional interface with a method
Before we can run the Hello application, we need to provide some program arguments for the method arguments of hello(). Right-click
Hello.java in Package Explorer and select Run As > Run Configurations. In Run Configurations, select the Arguments tab, specify arguments
in the Program arguments field, and click Apply. Then click Close.
To run the Hello.java application, right-click Hello.java in Package Explorer and select Run As > Java Application. The application output is
displayed in the Eclipse console, as shown in Figure 2.
Figure 2
Local Variables in Lambda ExpressionsA lambda expression does not define a new scope; the lambda expression scope is the same as the enclosing scope. For example, if a lambda
expression body declares a local variable with the same name as a variable in the enclosing scope, a compiler error—Lambda expression's
local variable i cannot re-declare another local variable defined in an enclosing scope—gets generated, as shown in
Figure 3.
Figure 3
A local variable, whether declared in the lambda expression body or in the enclosing scope, must be initialized before being used. To
demonstrate this, declare a local variable in the enclosing method:
int i;
Use the local variable in the lambda expression. A compiler error—The local variable i may not have been initialized—gets
generated, as shown in Figure 4.
Figure 4
A variable used in a lambda expression is required to be final or effectively final. To demonstrate this, declare a local variable and initialize the
local variable:
7/18/2014 Trying Out Lambda Expressions in the Eclipse IDE
Assign the variable in the lambda expression body. A compiler error—Variable i is required to be final or effectively final—
gets generated, as shown in Figure 5.
Figure 5
The variable i can be declared final as follows.
final int i=5;
Otherwise, the variable must be effectively final, which implies that the variable cannot be assigned in the lambda expression. Method parameter
variables and exception parameter variables from an enclosing context must also be final or effectively final.
The this and super references in a lambda body are the same as in the enclosing context, because a lambda expression does not introduce a
new scope, which is unlike the case with anonymous classes.
A Lambda Expression Is an Anonymous MethodA lambda expression is, in effect, an anonymous method implementation; formal parameters are specified and a value can be returned with a
return statement. The anonymous method must be compatible with the functional interface method it implements, as dictated by the following
rules.
The lambda expression must return a result that is compatible with the result of the functional interface method. If the result is void, the lambdabody is void-compatible. If a value is returned, the lambda body is value-compatible. The return value can be of a type that is a subtype of thereturn type in the functional interface method declaration.The lambda expression signature must be the same as the functional interface method's signature. The lambda expression signature cannot bea subsignature of the functional interface method's signature.The lambda expression can throw only those exceptions for which an exception type or an exception supertype is declared in the functionalinterface method's throws clause.To demonstrate that a lambda expression must return a result if the functional interface method returns a result, comment out the return
statement in the lambda expression that has the target type HelloService. Because the hello() method in the functional interface,
HelloService, has a return type of String, a compiler error is generated, as shown in Figure 6.
Figure 6
If the functional interface method declares the result as void and the lambda expression returns a value, a compiler error is generated, as shown
in Figure 7.
Figure 7
7/18/2014 Trying Out Lambda Expressions in the Eclipse IDE
If the lambda expression signature is not exactly the same as the functional interface method signature, a compiler error is generated. To
demonstrate this, make the lambda expression parameter list empty while the functional interface method declares two formal parameters. A
compiler error—Lambda expression's signature does not match the signature of the functional interface method—is
generated, as shown in Figure 8.
Figure 8
No distinction is made between a vararg parameter and its array equivalent. For example, a functional interface method declares an array-type
parameter as follows:
interface Int { void setInt(int[] i);
}
The parameter list of the lambda expression can declare a vararg parameter:
Int int1 =(int... i)->{};
Exception HandlingA lambda expression body must not throw more exceptions than specified in the throws clause of the functional interface method. If a lambda
expression body throws an exception, the throws clause of the functional interface method must declare the same exception type or its
supertype.
To demonstrate this, do not declare a throws clause in the hello method of the HelloService interface and throw an exception from the
lambda expression body. A compiler error message—Unhandled exception type Exception—is generated, as shown in Figure 9.
Figure 9
If the same exception type as the thrown exception is added to the functional interface method, the compiler error is resolved, as shown in Figure
10. But, a compiler error message is generated if the hello method is invoked using the reference variable to which the lambda expression
result is assigned, because the exception is not handled in the main method, which is also shown in Figure 10.
Figure 10
A Lambda Expression Is a Poly Expression
7/18/2014 Trying Out Lambda Expressions in the Eclipse IDE
Generic lambdas are not supported. A lambda expression cannot introduce type variables.
Lambda Expressions in a GUI ApplicationGUI components in the java.awt package make use of the java.awt.event.ActionListener interface to register action events from a
component. The java.awt.event.ActionListener interface is a functional interface with only one method: actionPerformed(ActionEvent
e).
A java.awt.event.ActionListener is registered with a component using the addActionListener(ActionListener l) method. For
example, a java.awt.event.ActionListener could be registered with a java.awt.Button component using an anonymous inner class in
the application to count the number of times a Button object called b has been clicked, as follows. (See "How to Write an Action Listener" for
more details.)
b.addActionListener (new ActionListener() { int numClicks = 0; public void actionPerformed(ActionEvent e) { numClicks++; text.setText("Button Clicked " + numClicks + " times"); } });
A lambda expression can be used instead of the anonymous inner class to make the syntax more concise. The following is an example of using
a lambda expression to register an ActionListener with a Button component:
The parentheses for specifying the parameter can be omitted for a single-parameter lambda expression. The target type of the lambda
expression—the functional interface ActionListener—is inferred from the context, which is a method invocation.
Using Lambda Expressions with Some Common Functional InterfacesIn this section, we will discuss how some common functional interfaces can be used with lambda expressions.
The FileFilter InterfaceThe FileFilter interface has a single method, accept(), and is used to filter files. In The Java Tutorials ImageFilter example, the
ImageFilter class implements the FileFilter interface and provides implementation for the accept() method. The accept() method is
used to accept just the image files (and directories) using a Utils class.
We could use a lambda expression that returns a boolean to provide implementation for the FileFilter interface, as shown in Listing 2.
import java.io.FileFilter;import java.io.File;
public class ImageFilter {
public static void main(String[] args) { FileFilter fileFilter = (f) -> { String extension = null; String s = f.getName(); int i = s.lastIndexOf('.');
if (i > 0 && i << s.length() - 1) { extension = s.substring(i + 1).toLowerCase(); } if (extension != null) {
File file = new File("C:/JDK8/Figure10.bmp"); System.out.println("File is an image file: " + fileFilter.accept(file));
}}Listing 2
The output from the ImageFilter class is shown in the Eclipse console in Figure 11.
Figure 11
The Runnable InterfaceIn The Java Tutorials "Defining and Starting a Thread" section, the HelloRunnable class implements the Runnable interface, and a Thread is
created using an instance of the HelloRunnable class. A Runnable for the Thread can be created using a lambda expression, as shown in
Listing 3. The lambda expression does not have a return statement, because the method run() in Runnable has result as void.
import java.lang.Runnable;
public class HelloRunnable {
public static void main(String args[]) { (new Thread(() -> { System.out.println("Hello from a thread"); })).start(); }}
Listing 3The output from the HelloRunnable class is shown in Figure 12.
The PathMatcher InterfaceThe java.nio.file.PathMatcher interface is used to match paths. The functional interface has a single method, matches(Path path), that
is used to match a Path. We can use a lambda expression to provide the implementation for the matches() method, as shown in Listing 6. The
lambda expression returns a boolean and the target type is the functional interface PathMatcher.
The output from the FileMatcher class is shown in Figure 14.
Figure 14
The Comparator InterfaceThe functional interface Comparator has a single method: compares(). The interface also has the equals() method, but the equals() method
is also in the Object class. A functional interface can have Object class methods in addition to one other method. If we were to compare
instances of an Employee entity using Comparator, we would first define the Employee POJO, which has properties and getter/setters for empId,
7/18/2014 Trying Out Lambda Expressions in the Eclipse IDE
while (litr.hasNext()) { Employee element = litr.next(); System.out.print(element.getLastName() + " "); }
}}Listing 9
The output from EmployeeSort is shown in Figure 15.
Figure 15
How Are the Target Type and Lambda Parameter Type Inferred?For lambda expressions, the target type is inferred from the context. A lambda expression can be used only in contexts in which the target type can
be inferred. Such contexts are a variable declaration, an assignment statement, a return statement, an array initializer, method or constructor
arguments, a lambda expression body, a conditional expression, and a cast expression.
The lambda formal parameters types are also inferred from the context. In all the preceding examples except the Hello example in Listing 1, the
parameter types are inferred from the context. In subsequent sections, we discuss some of the contexts in which the lambda expressions could
be used.
Lambda Expressions in return StatementsA lambda expression can be used in a return statement. The return type of the method in which a lambda expression is used in a return
statement must be a functional interface. For example, include a lambda expression in a return statement for a method that returns a Runnable,
as shown in Listing 10.
import java.lang.Runnable;
public class HelloRunnable2 {
public static Runnable getRunnable() { return () -> { System.out.println("Hello from a thread"); };
7/18/2014 Trying Out Lambda Expressions in the Eclipse IDE
The lambda expression does not declare any parameters, because the run() method of the Runnable interface does not declare any formal
parameters. The lambda expression does not return a value, because the run() method has the result as void. The output from Listing 10 is
shown in Figure 16.
Figure 16
Lambda Expressions as Target TypesLambda expressions themselves can be used as target types for inner lambda expressions. The call() method in Callable returns an
Object, but the run() method in Runnable doesn't have a return type. The target type of the inner lambda expression in the HelloCallable2
class is a Runnable, and the target type of the outer lambda expression is Callable. The target type is inferred from the context, which is an
assignment statement to a reference variable of type Callable<Runnable>.
In Listing 11, the inner lambda expression, () -> {System.out.println("Hello from Callable");}, is inferred to be of type Runnable
because the parameter list is empty and the result is void; the anonymous method signature and result are the same as the run() method in
the Runnable interface. The outer lambda expression, () -> Runnable, is inferred to be of type Callable<Runnable> because the call()
method in Callable<V> does not declare any formal parameters and the result type is type parameter V.
import java.util.concurrent.Callable;
public class HelloCallable2 {
public static void main(String[] args) { try {
Callable<Runnable> c = () -> () -> { System.out.println("Hello from Callable"); }; c.call().run();
Lambda Expressions in Array InitializersLambda expressions can be used in array initializers, but generic array initializers cannot be used. For example, lambda expressions in the
following generic array initializer would generate a compiler error:
Casting Lambda ExpressionsSometimes the target type of a lambda expression can be ambiguous. For example, in the following assignment statement, a lambda expression
is used as a method argument to the AccessController.doPrivileged method. The target type of the lambda expression is ambiguous
because more than one functional interface—PrivilegedAction and PrivilegedExceptionAction—could be the target type of the lambda
expression.
String user = AccessController.doPrivileged(() -> System.getProperty("user.name"));
A compiler error—The method doPrivileged(PrivilegedAction<String>) is ambiguous for the type AccessController—gets
generated, as shown in Figure 20.
Figure 20
We can use a cast to the lambda expression to specify the target type as PrivilegedAction<String>, as in the UserPermissions class
Lambda Expressions in Conditional ExpressionsLambda expressions can be used in ternary conditional expressions, which evaluate one of the two operands based on whether a boolean
condition is true or false.
In the HelloCallableConditional class shown in Listing 14, the lambda expressions—() -> "Hello from Callable: flag true") and
() -> "Hello from Callable: flag false")—constitute the two alternative expressions to evaluate. The target type of the lambda
expressions is inferred from the context, which is an assignment statement to a Callable<String> reference variable. Subsequently, the
reference variable is used to invoke the call() method.
import java.util.concurrent.Callable
public class HelloCallableConditional {
public static void main(String[] args) { try {
boolean flag = true; Callable<String> c = flag ? (() -> "Hello from Callable: flag true") : (() -> "Hello from Callable: flag false");
The output from HelloCallableConditional is shown in Figure 22.
Figure 22
Inferring the Target Type in Overloaded MethodsWhen you invoke a method that is overloaded, the method that best matches the lambda expression is used. The target type and the method
argument type are used to resolve the best method.
7/18/2014 Trying Out Lambda Expressions in the Eclipse IDE
The output from HelloCallableConditional is shown in Figure 23.
Figure 23
this in Lambda ExpressionsOutside a lambda expression, this refers to the current object. In a lambda expression also, this refers to the enclosing current object. Lambda
expressions that do not refer to members of the enclosing instance do not store a strong reference to it, which solves a memory leak problem that
often occurs in inner class instances that hold a strong reference to the enclosing class.
In the example in Listing 16, Runnable is the target type of a lambda expression. In the lambda expression body, a reference to this is specified.
When an instance of Runnable r is created and the run() method is invoked, the this reference invokes the enclosing instance and a String
value of the enclosing instance is obtained from the toString() method. The message Hello from Class HelloLambda gets output.
public class HelloLambda { Runnable r = () -> { System.out.println(this); };
public String toString() { return "Hello from Class HelloLambda"; }
public static void main(String args[]) { new HelloLambda().r.run(); } }Listing 16
The output from HelloLambda is shown in Figure 24.
7/18/2014 Trying Out Lambda Expressions in the Eclipse IDE
Lambda Expression Parameter NamesNew names are created for the formal parameters of a lambda expression. If the same names as the local variable names in the enclosing
context are used as lambda expression parameter names, a compiler error gets generated. In the following example, lambda expression
parameter names are specified as e1 and e2, which are also used for local variables Employee e1 and Employee e2.
Employee e1 = new Employee(1,"A", "C"); Employee e2 = new Employee(2,"B","D" ); List<Employee> list = new ArrayList<Employee>(); list.add(e1);list.add(e2);
A compiler error is generated for lambda expression parameter e1, as shown in Figure 25.
Figure 25
A compiler error is also generated for lambda expression parameter e2, as shown in Figure 26.
Figure 26
References to Local VariablesIn providing an alternative to anonymous inner classes, the requirement for local variables to be final in order to be accessed in a lambda
expression was removed. The requirement for a local variable to be final to be accessed from an inner class is also removed in JDK 8. In JDK 7,
a local variable accessed from an inner class must be declared final.
The requirement for a local variable to be used in an inner class or a lambda expression has been modified from "final" to "final or effectively
final."
Method ReferencesA lambda expression defines an anonymous method with a functional interface as the target type. Instead of defining an anonymous method,
existing methods with a name can be invoked using method references. In the EmployeeSort example in Listing 9, the following method
invocation has a lambda expression as a method argument.
The method reference doesn't even have to be an instance method of the object in which it is used. The method reference can be an instance
method of any arbitrary class object. For example, a String List can be sorted using the compareTo method from the String class with a
method reference:
String e1 = new String("A"); String e2 = new String("B"); List<String> list = new ArrayList<String>(); list.add(e1);list.add(e2);Collections.sort(list, String::compareTo);
Method references are a further simplification of lambda expressions.
Constructor ReferencesMethod references are used for method invocations, and constructor references are used with constructor invocations. Method references and
constructor references are lambda conversions, and the target type of method references and constructor references must be a functional
interface.
In this section, we discuss constructor references using a Multimap as an example. Multimap is a Google Collections utility. A Multimap for
image types is created as follows:
Multimap<ImageTypeEnum, String> imageTypeMultiMap = Multimaps .newListMultimap( Maps.<ImageTypeEnum, Collection<String>> newHashMap(), new Supplier<List<String>>() { public List<String> get() { return new ArrayList<String>(); } });
In the Multimap example, a Supplier<List<String>> is created using a constructor as follows:
new Supplier<List<String>>() { public List<String> get() { return new ArrayList<String>(); } }
The constructor returns an ArrayList<String>. Using a constructor reference, the Multimap can be created with a simplified syntax as follows:
To test the ImageTypeMultiMap class, we need to download the Guava library guava-14.0.1.jar from https://code.google.com/p/guava-
libraries/ and add the guava-14.0.1.jar to the Java build path. The output from ImageTypeMultiMap is shown in Figure 27.
Figure 27
Virtual Extension MethodsEncapsulation and reusability of an interface are the main benefits of an interface. But an interface has a disadvantage in that that all the interface
methods must be implemented in a class that implements an interface. Sometimes only a few of the methods are required from an interface, but
method implementations for all the interface methods must be provided when the interface is implemented. Virtual extension methods provide a
fix for the issue.
Virtual extension methods are the methods in an interface that have a default implementation. If an implementing class does not provide an
implementation for the method, the default implementation is used. An implementing class can override the default implementation or provide a
new default implementation.
Virtual extension methods add the provision to expand the functionality of interfaces without breaking backward compatibility of classes that are
already implementing an earlier version of the interface. The default implementation in a virtual extension method is provided using the default
keyword. A virtual extension method provides a default implementation and, therefore, cannot be abstract.
The java.util.Map<K,V> class in JDK 8 provides several methods that have default implementations:
default V getOrDefault(Object key,V defaultValue)default void forEach(BiConsumer<? super K,? super V> action)default void replaceAll(BiFunction<? super K,? super V,? extends V> function)default V putIfAbsent(K key,V value)default boolean remove(Object key,Object value)default boolean replace(K key,V oldValue,V newValue)default V replace(K key,V value)default V computeIfAbsent(K key,Function<? super K,? extends V> mappingFunction)default V computeIfPresent(K key,BiFunction<? super K,? super V,? extends V> remappingFunction)default V compute(K key,BiFunction<? super K,? super V,? extends V> remappingFunction)default V merge(K key,V value,BiFunction<? super V,? super V,? extends V> remappingFunction)To demonstrate that methods with default implementation do not need to be implemented when an interface is implemented by a class, create a
class called MapImpl that implements the Map<K,V> interface:
public class MapImpl<K,V> implements Map<K, V> {
}The complete MapImpl class with implementation for the methods that do not provide a default implementation is shown in Listing 18.