Here I was thinking Java 9 was still quite new when I realized Java 10 has been released. Time to have a look.

@SafeVarargs

@SafeVargs are now allowed on private instance methods. Actually, let’s start by having a look at what @SafeVarargs are in the first place.

Java allows us to put anything in a collection. For instance, the following code would compile but throw a ClassCastException at runtime since we can’t cast Integer to String.

List list = new ArrayList();
list.add(1);
String str = (String) list.get(0);

We can move this error to compile time (“incompatible types”) by enforcing the type of the collection using type parameters. Also most IDE:s would complain.

List<String> list = new ArrayList<>();

However, this information is not included in the bytecode used by the JVM, which can become an issue when we use varargs. Here’s an example from the Java API Docs on the annotation:

private static void m(List<String>... list) {
        Object[] array = list;
        array[0] = Arrays.asList(42);
        String str = list[0].get(0);
}

At runtime, our parameter varargs of type List of String become an object array. We can insert a list of integers, so when we attempt to retrieve a String from what we thought was a list of String, we get a ClassCastException since we’re actually dealing with an array of Object that contains an Integer.

Without the @SafeVarargs annotation, IntelliJ correctly warns of “Possible heap pollution from parameterized vararg type.” Heap pollution refers to the situation we’re in, where a variable of what we view as a certain parameterized type, refers to an object of a different type.

If we’re certain our code doesn’t do anything dangerous and we don’t want the warning, we can turn it off with the @SafeVarargs annotation. Now we can do this with a method that isn’t static:

@SafeVarargs
private void m(List<String>... list) {
    // do stuff
}

Not a huge change in the language, but hey why not. 🙂

try-with-resources

try-with-resources statements now allow final or effectively final variables to be used, rather than declaring a new variable. Perhaps not revolutionary, but makes sense.

Resource resource = new Resource(); // AutoCloseable
try (resource) {
    // do stuff
}

Java Platform Module System

This looks really interesting. I haven’t had a chance to use modules in a production system yet, but they look like a great addition to Java. If Java 8 changed things on a smaller scale with features like lambdas, the module system affects the structure of applications.

Before Java 9, we could structure code using a combination of classes and packages, and encapsulate it using the class level access modifiers private, protected, “package private” and public. If we wanted to share code between packages, we had to make the code accessible to everyone using the public modifier.

With Java 9, we can organize packages using modules and choose which modules – groups of packages – to export and which are for internal use only.

Let’s try this out.

I’m using IntelliJ, which has a guide to Java 9 modules in Intellij on their blog. Following that guide, let’s create an empty project and add two IntelliJ Java modules. One such IntelliJ module will correspond to one Java 9 module — but they are not the same thing. I’m calling my project module_demo which gives the project the following structure.

./module_demo/one/
./module_demo/two/

Let’s add some example code to module two that prints something, and export the package using a module-info.java file placed in the Sources Root.

// two/src/c/Printer
package b;
public class Printer {
    public void printStuff() {
        System.out.println("stuff");
    }
}
// two/src/module-info.java
module two {
    exports b;
}

We can now use this code in the first module.

// one/src/a/Application
package a;
import b.Printer;

public class Application {
    public static void main(String[] args) {
        new Printer().printStuff();
    }
}
// one/src/module-info.java
module one {
    requires two;
}

The code in module one will now print the message from module two. This covers the requires and exports keywords. Let’s have a look at two more keywords, provides ... with and uses, to see how we can use these to remove the tight coupling between module one and the Printer implementation in module two.

Let’s start by changing package two to implement a Printer interface.

public interface Printer {
    void print();
}
package b;

public class StuffPrinter implements Printer {
    @Override
    public void print() {
        System.out.println("stuff");
    }
}

We can now use provides ... with to provide an implementation of the interface.

import b.Printer;
import b.StuffPrinter;

module two {
    exports b;
    provides Printer with StuffPrinter;
    uses Printer;
}

We use this by adding uses Printer; to our module-info.java in module one. That way we can get all implementations of Printer using ServiceLoader.

ServiceLoader
        .load(Printer.class)
        .forEach(Printer::print);

We could also, for instance, move the ServiceLoader to the Printer interface.

public interface Printer {
    void print();

    static Iterable<Printer> getPrinters(){
        return ServiceLoader.load(Printer.class);
    }
}
Printer
    .getPrinters()
    .forEach(Printer::print);

That way we can instead call Printer directly to get all Printer implementations. Functionally the same, but now we don’t have to know the underlying mechanism uses a ServiceLoader.

In this case there’s only one implementation, but we could imagine there being multiple in a real application. We could chose between them using, for instance, a factory or strategy pattern.