Quick and Easy Conversion to Java SE 8 with NetBeans IDE 8
by Geertjan Wielenga, Lyle Franklin and Alex Gyori
Published May 2014
New tools in NetBeans 8 for leveraging the functional features of Java SE 8
In this article, we’re going to look at new and helpful tools in NetBeans IDE 8 that enable developers to use the functional features of Java SE 8. Java SE 8 introduces lambda expressions to the language. Figure 1 shows a lambda expression in Java. The parameters are shown on the left side of the lambda arrow, while the method body is shown to its right.
Originally published in the May/June 2014 issue of Java Magazine. Subscribe today.
NetBeans IDE 8 provides two automated refactorings that leverage this new language feature. The first refactoring converts anonymous inner classes to lambda expressions, and the second refactoring converts
for loops that iterate over collections to functional operations that use lambda expressions.
We’ll start by looking at the first refactoring. Anonymous inner classes such as the one shown in Figure 2 are useful constructs, although the syntax is unnecessarily verbose. Lambda expressions provide a more concise replacement for anonymous inner classes that declare only a single method.
NetBeans IDE 8 highlights valid refactoring sites (see Figure 3), and when you select the Java hint in the left sidebar, the IDE performs the conversion automatically. As you can see in Figure 4, the new syntax is much more concise and easier to read.
While this transformation might seem simple at first glance, the IDE performs static analysis to ensure that the transformation is performed safely. For example, examine the code snippet in Figure 5.
In this method, the
doPrivileged method is overloaded and can accept either a
PrivilegedAction or a
PrivilegedExceptionAction. When you perform the refactoring, the IDE automatically adds a cast to the correct type (see Figure 6).
If this cast were not added, the resulting lambda expression would be ambiguous, as shown in Figure 7, and a compilation error would result. In Figure 8, a variable declaration in the anonymous inner class hides or shadows a variable declared in the enclosing scope.
While variable shadowing is legal in anonymous inner classes, lambda expressions do not allow this. The IDE detects variable shadowing and automatically renames shadowing variables to avoid compilation errors. As you can see in Figure 9, a 1 was appended to the variable name to avoid any errors.
The second refactoring, which is shown in Figure 10, highlights another feature of Java SE 8: internal iterators. Java SE 8 has added several methods to the Collections API that take a lambda expression as an argument and enable functional operations over collections. Some examples of these operations are
anyMatch, to name a few. The IDE can refactor existing external iterators, such as enhanced
for loops, to utilize these new internal iterators.
In the example in Figure 11, the total number of errors in a collection of rules is calculated. Although it might not be obvious, this example is analogous to a
filter MapReduce operation. The
if statement filters out elements, the function call maps a rule to the number of errors, and the compound assignment adds each count to an accumulator. The IDE can automatically refactor this code to use functional operations, as shown in Figure 12.
This example also shows that the types of the parameters of the lambda expressions can be omitted and can instead be inferred by the compiler. However, you might find it useful for readability or style reasons to let the IDE create the parameter types for you (see Figure 13).
As you can see in Figure 14, in line 10, the parameter type has now been set explicitly. Conversion to method references—the alternative way of working with lambda expressions—is also supported by the IDE (see Figure 15). As shown in Figure 16, the
:: syntax has now replaced the
-> syntax of standard lambda expressions.
Without the aid of an automated tool, these refactorings are time consuming and can introduce subtle bugs if done incorrectly. NetBeans IDE performs these refactorings quickly, while preserving the original program behavior.
In addition to the quick hint mode of operation, the IDE can function in batch mode. As shown in Figure 17, you can select a single file, an entire project, or all open projects, and the IDE will generate a preview of all possible conversions for that selection.
Instead of using the batch refactoring tool, whenever you see a Java hint in the left sidebar you can specify that the refactoring should be done across a scope of your choice (see Figure 18).
Even projects with hundreds of thousands of lines of code can be scanned in a matter of seconds. The preview allows for fine-grained control over which conversion should take place, or it can simply refactor all possible conversions (see Figure 19).
NetBeans IDE 8 provides the tools you need to smoothly and correctly upgrade your imperative code constructs to the new functional style introduced in Java SE 8. Its automated refactoring capability can refactor your code to use functional operations, and its batch mode allows you to specify the scope of the refactoring. Get started converting your code today!
Geertjan Wielenga is a product manager in the Oracle Developer Tools organization, focused on NetBeans IDE.
Lyle Franklin is pursuing a master’s degree in computer science at the University of Southern California.
Alex Gyori is a PhD student in software engineering at the University of Illinois at Urbana-Champaign.