for an anonymous instance of a Functional Interface that implements the Interface's single abstract method. (arg1, … argn) -> { statement; statement; …; return v; }
return v; } … is, essentially: new FI() { public V f(arg1, … argn){ statement; statement; …; return v; } } Do NOT forget that lambdas are NOT references to functions!
x -> x + x; // Compilation error: Method call expected int z = fn(3); // Compilation error: operator ‘+’ cannot… int y = (x -> x + x)(1); int y = (x -> x + x).apply(1);
instance of a Functional Interface. You must call its single abstract method. @FunctionalInterface public interface Fn { void p(String arg); } Fn fn = s -> System.out.println(s); fn.p("Hello");
main(String... args) { // code... } … that we want to replace with a lambda public static void main(String... args) { Task<I, O> task = in -> { // code... }; new Thread(() -> { task.run(in); }).start(); }
subject to these constraints http://www.javac.info/closures-v05.html • captured non-final variable • a reference to this • break and continue statements • a return statement • throwing an exception
final. … but you better not try to change them! String[] args = new String[]{"one", "two"}; int i = 0; Predicate<String> pred = x -> x.equals(args[i]); System.out.println(pred.test("one")); // true args[0] = "three"; // ok!! System.out.println(pred.test("one")); // false i = 1; // Causes compilation error up there ^^
int x; private Predicate<Integer> p2 = new Predicate<Integer>() { @Override public boolean test(Integer n) { return n == OuterClass.this.x; } }; private Predicate<Integer> p1 = n -> n == x;
determines type @FunctionalInterface public interface F1 { String f(String n); } @FunctionalInterface public interface F2 { Integer f(Integer n); } F1 fn1 = x -> x + x; F2 fn2 = x -> x + x; fn1.f(2); // Compilation error: Fn1 cannot be applied to int fn1.f("a"); // "aa" fn2.f(2); // 4 fn2.f("a"); // Compilation error: Fn2 cannot be applied to String
type must be inferred from context. // Compilation error: cannot resolve getClass (x -> x).getClass().getCanonicalName(); // Compilation error: // cannot cast <lambda parameter> as Object x -> (Object) x;
{ void doSomething(); void doSomethingElse(); //added } //Compilation error: // must implement doSomethingElse public class Server implements API { public void doSomething() { } }; … and implementations no longer compile
will not satisfy a requirement from another interface: public interface I1 { void F(); } public interface I2 { default void F(){ … } } // Compilation error: F undefined public class C implements I1, I2 { … }
in a super interface: A call to C.f() will print the string “I2” public interface I1 { default void f() { System.out.println(”I1”) } } public interface I2 extends I1 { default void f() { System.out.println(”I2”) } } public class C implements I2 { … }
to, e.g., the Collections API public interface Collection<E> { // … API as it has been since Java 1.2 default Stream<E> parallelStream() { … } default Spliterator<E> spliterator() { … } default Stream<E> stream() { … } }
"a"); s.forEach(System.out::println); Don’t evaluate an infinite stream! Stream s = Stream.iterate("a", c -> c + "a"); s.distinct() .limit(10) .forEach(System.out::println); Really! Don’t evaluate an infinite stream!