Tuesday, July 17, 2012

Java 8, Lambda and method references

It could be said that Java 8 with Lambda has a simple form of structural typing.

A method on an object can be transformed into an instance of a matching functional interface. A functional interface is an interface with one method. This is achieved by using method references. For more details see Brian Goetz's State of the Lambda document, section 8.

For example, one can do this:

public class Main {
  public static class NotAutoCloseable {
    public void close() throws Exception {
      System.out.println("CLOSE");
    }
  }

  public static void main(String... args) throws Exception {
    NotAutoCloseable nac = new NotAutoCloseable();
    try (AutoCloseable ac = nac::close) {
    }
  }
}

The class NotAutoCloseable does not implement AutoCloseable but it has a method, close, that matches the functional interface AutoCloseable. So  NotAutoCloseable#close can be transformed into an instance of AutoCloseable using the method reference nac::close.

This is equivalent to the following with a lambda expression:

    try (AutoCloseable ac = () -> { nac.close(); }) {
    }

The variable nac is effectively final.

Compiling the above Main class currently generates an inner class that implements AutoCloseable and encapsulates the invocation of nac.close(). Thats gonna change, expect to see invokedynamic instructions in the byte code! Such an instruction will describe a recipe to construct the lambda expression at runtime without specifying the implementation details.

In addition to method references there are also constructor references. So constructors can be transformed into factories.

I think method and constructor references are expressive little gems, but they are one of many new features in the Java language, Java virtual machine and Java libraries that combined will bring significant improvements in Java 8.

1 comment:

  1. One can add that its not necessary for the method to be names close(). The parameter and return type has to match, that all. An alternative listing:

    public class Main {
    void c() {
    System.out.println("CLOSE");
    }

    public static void main(String... args) throws Exception {
    Main nac = new Main();
    try (AutoCloseable ac = nac::c) {
    }
    }
    }

    ReplyDelete