Most notable Java 8 features explained

(Daniel Pfeifer)
At my current client we're already now preparing to go into production with Java 8 and while most still haven't had the opportunity to work with Java 8 productively, I thought I'd make my take on what I find most notable for a Java developer and try to describe it in a simple fashion without you having to read entire book-style blog posts about a single feature.
Let's dive right in!

PermGen gone, where are my class sigs?

With the departure of the permanent generation, you can just drop the -XX:PermSize/MaxPermSize flags from your list of startup arguments. Does this mean you can never run out of permgen space any more? Well, sort of. However, since it's native memory that statics and signatures are pushed into, you may still run out of native memory if you have class loader leaks. Although your app may survive a lot longer considering you may have a lot of native memory, a leak is still a leak.

A little bit of Scala, perhaps?

Java 8 has the new immutable class static, which, combined with lambda expressions can do some pretty nice stuff.

Optional<NestedObject> opt = Optional.ofNullable(nestedObject);
NestedObject interestingObject opt.filter(no -> no.getContent() != null).orElse(otherNestedObject);

Option allows other fancy things, but the above will eliminate a bunch of if/else and null checks and the resulting object will be one that we are interested in ( as interesting as a dummy variable name can be ;-) ).

Commons Codec for simple Base64?

Ever wondered why something as simple as Base64 en-/decoding wasn't part of the public Java API (well, there are internal encoders/decoders, but using stuff from the sun.-package is probably not a great idea). In Java 8 you can now do the following without adding any third party commons codec library:

Base64.getDecoder().decode(aByteArray);

... or ...

Base64.getEncoder().encode(aByteArray); // or encodeToString(aByteArray)

Good bye, anonymous inner class boilerplate

Ever thought about the fact that you write several lines of code for one single statement when dealing with anonymous inner classes (like event handlers)?
Say that you have the following in Java 7:

object.addEventHandler(new EventHandler() {
  @Override
  public void handleEvent(Event e) {
    System.out.println(e.toString());
  }
}
In Java 8 you can simply do:

object.addEventHandler(e -> System.out.println(e.toString());

Sort my array, but fast this time.

In Java 7 you could already employ the Fork/Join framework to implement a fast parallel array sorter. In Java 8, Oracle has done the job for you.

Arrays.parallelSort(myLargeArray, myComparator);

Be aware though, the overhead of forking off a bunch of threads won't give you any benefit unless it's a large array!

Method reduction

Previously, you were always required to explicitly declare all parameters that a method takes explicitly. In Java 8, however, you're able to reduce a single method call down to it's bare essentials. Say that you want to sort an array with a normal Comparator. You would implement the Comparator and hand the new instance of it to the sort()-method. This produces quite a bunch of lines of code. Java 8 can not only infer that you are trying to compare (if you follow the expected signature, that is), it can also reduce the amount of method calling to handing it a simple method name.

Say that your class Car has a method with the signature public int compareCar(Car one, Car two) you are able to reduce the call to sort() to it's bare essentials:

Arrays.sort(cars, Car::compareCar)

Using streams for fancy collection processing

Remember those days where you had to write a for-loop to fetch out everything interesting from a collection? Those days are over with Java 8's streams. Say you want to have a new filtered list of all usernames of a collection of Accounts.

List<String> usernames = accountList.stream().filter(a -> a.getGender() == Gender.FEMALE && a.getAge() >= 18).map(a -> a.getUsername()).collect(Collector.toList());

Mixins, sort of...

Java 8 now allows you to provide default implementations for methods in interfaces. Thus, you can add methods to your interface and well, you can implement lot's of interfaces, can't you? If multiple interfaces implement the same methods, it won't compile (unless you don't specify the actual implementation for a default method). Also, default methods aside, there are also static methods in interfaces. The latter can not be implemented in the inheritor, while default methods can.

public interface Foo {
    void init();

    static void printSomething() {
         System.out.println("Something");
    }

    default void printSomethingElse() {
        System.out.println("Something else");
    }
}

public class Bar implements Foo {
      public void init() {
          // Do something
      }
}

Now we can call all three methods and if we added more interfaces with default methods, we could enrich the class Bar even more. Be aware though, only printSomethingElse() can be overriden in it's implementation.


Happy coding!