Java 8 Features
As with previous Java releases, JDK 8 contains a large number of new features.
Although all are important, three stand out. They are:
Lambda expressions
The stream API in java.util.stream
Default interface methods
Combined, lambda expressions, the stream API, and default methods fundamentally
expand the scope, power, and range of Java. Let's take a brief look at each.
Lambda Expressions
The single most important new JDK 8 feature is the lambda expression. Java
programmers have been anticipating lambda expressions for some time, and JDK 8
delivers a powerful, yet flexible implementation. Lambda expressions are so important
because they add functional programming features to Java. Their use can simplify and
reduce the amount of source code needed to create certain constructs, such as some types
of anonymous classes. This is particularly helpful when implementing a number of
commonly used event handlers, for example. Lambdas also make it easy to pass what is,
in essence, a piece of executable code as an argument to a method. To support lambda
expressions Java has been expanded by the inclusion of a new operator (the –>) and a
new syntax element. Make no mistake, the impact of the lambda expression will be
significant, affecting both the way you design and implement Java code.
To give you an idea of the benefits that lambda expressions bring, consider the
following ActionEvent handler, which uses the traditional, anonymous class, approach:
myButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
myLabel.setText("Button pressed.");
}
});
With JDK 8, this event handler can be written using a lambda expression, as shown here:
myButton.addActionListener(
(ae) -> myLabel.setText("Button pressed.")
);
As you can see, this is shorter code that is more direct and to the point. Of course,
lambda expressions have many uses beyond simplifying event handlers. They offer a
powerful solution to many programming challenges.
The Stream API
JDK 8 adds many new features to Java's API library. Arguably, the most
important is the new stream API, which is packaged in java.util.stream. In the context
of the stream API, a stream represents a sequence of data. The key aspect of the stream
API is its ability to perform pipeline operations that search, filter, map, or otherwise
manipulate data.
Assume that you have a list that stores employee names, the department in which
they work, their e-mail addresses, and their phone numbers. Using the stream API, you
can efficiently pipeline the operations that search for entries that match some criterion,
such as department name, sort the matching items, and then extract only the e-mail
addresses, for example. Often, you will use lambda expressions to specify the behavior of
these types of operations. Furthermore, in many cases, such actions can be performed in
parallel, thus providing a high level of efficiency, especially when large data sets are
involved. Put simply, the stream API provides a powerful means of handling data in an
efficient, yet easy to use way.
Default Methods
In the past, no method in an interface could include a body. Thus, all methods in
an interface were implicitly abstract. With the release of JDK 8, this situation has
changed dramatically. It is now possible for an interface method to define a default
implementation. This new capability is called the default method.
A primary motivation for the default method was to provide a means by which
interfaces could be expanded without breaking preexisting code. As you know, when a
non-abstract class implements an interface, there must be implementations for all
methods defined by that interface. In the past, if a new method was added to a popular,
widely-used interface, then the addition of that method would break preexisting code,
because no implementation would be found for that new method in preexisting classes.
The default method solves this problem by supplying an implementation that will be used
if no other implementation is explicitly provided. Thus, the addition of a default method
will not cause preexisting code to break. This enables interfaces to be gracefully evolved
over time without negative consequences.
Another motivation for the default method was the desire to specify methods in an
interface that are, essentially, optional, depending on how the interface is used. In the
past, optional methods defined by an interface were still required to be implemented even
though they were unused. Often, this was done by providing an empty implementation.
Today, a default implementation can be provided for an optional method, thus
eliminating the tedium of creating empty, placeholder implementations.
Of Course, There is More
Although lambda expressions, the stream API, and default methods are the
features that have the most profound impact on the character and nature of Java, JDK 8
includes several others. Among these are method references, repeating annotations, and
annotations on type uses. As you would expect, there are also substantial updates and
enhancements to the Java library, including a new date and time API and the functional
interfaces packaged in java.util.function. A functional interface is an interface that
defines one and only one abstract method. Functional interfaces provide support for
lambda expressions and method references. JDK 8 also puts JavaFX front and center.
This powerful GUI framework is something that no Java programmer should ignore.
With the release of JDK 8, the world of Java programming is once again
changing. Many of the techniques that programmers have relied on in the past are now
being replaced by better, more powerful constructs. Programmers who fail to adopt the
new strategies will soon find themselves left behind. Frankly, in the competitive world of
programming, no Java programmer can afford to be left behind.