Java 8 introduced a change named Java's biggest ever -- lambda expressions. In this talk we'll explore lambda expressions, when and how to use them, then dive even deeper and see how they work under the hood.
When can we use λs? @FunctionalInterface public interface Comparator { int compare(T o1, T o2); } @FunctionalInterface public interface Predicate { boolean test(T t); }
When can we use λs? Java < 8 new Thread(new Runnable() { @Override public void run() { System.out.println("Lambdas can have"); System.out.println("multiple statements"); } }).start();
Desugaring class A { public void foo() { List list = ... list.forEach([await link of lambda$1 Consumer]); } private static void lambda$1(String s) { System.out.println(s); } }
Desugaring class B { public void foo() { List list = ... int factor = ... list.map([await link of lambda$1 as Function]); } private static Integer lambda$1(int factor, Integer n) { return n * factor; } }
The Lambda Metafactory ● “invokedynamic” encountered ● Metafactory is invoked once ● ...returns a specific “Lambda Factory” ● Call site linked to the specific factory forever
The Lambda Factory class A { public void foo() { List list = ... list.forEach([lambda$1 factory]); } private static void lambda$1(String s) { System.out.println(s); } }
But why? ● Try not to touch the bytecode specification ● Delegates lambda handling to the JVM ● While allowing the compiler minimal control ● Enabled runtime optimization and analysis
But why? ● Try not to touch the bytecode specification ● Delegates lambda handling to the JVM ● While allowing the compiler minimal control ● Enabled runtime optimization and analysis ● Allow flexibility in internal implementation