Implementation of the Single Abstract Method (SAM) of a Functional Interface.
BinaryOperator<Long> longAdder = (Long x, Long y) -> {return x + y;};
This line of code does not add two long values. longAdder is the implemention of the apply method in BinaryOperator interface. When the apply method is called on longAdder, two long values will be summed.
longAdder.apply(Long.valueOf(1), Long.valueOf(2)); // Long[3]
(parameters) -> {lambda-body} // -> is the lambda operator
@FunctionalInterface
interface Foo {
void foo();
}
@FunctionalInterface
interface Baz {
void baz(Integer i, String s);
}
class App {
void fooBarBaz() {
Foo foo = () -> {};
Baz baz = (Integer i, String s) -> {};
}
}
@FunctionalInterface
interface Baz {
void baz(Integer i, String s);
}
class App {
void fooBarBaz() {
Baz baz = (i, s) -> {};
// This is not allowed:
// Baz baz = (Integer i, s) -> {};
}
}
@FunctionalInterface
interface Baz {
void baz(Integer i, String s);
}
class App {
void fooBarBaz() {
Baz baz = (final Integer i, final String s) -> {};
}
}
@FunctionalInterface
interface FooTest {
void bar(Integer i);
}
class App {
void fooBarBaz() {
FooTest bar = i -> {};
// This is not allowed:
// FooTest bar = Integer i -> {};
}
}
@FunctionalInterface
interface Foo {
void foo(String s);
}
@FunctionalInterface
interface FooTest {
Integer bar(String s);
}
class App {
void fooBar() {
Foo foo = s -> {System.out.println(s);};
FooTest bar = s -> {return -1;};
}
}
void return@FunctionalInterface
interface Foo {
void foo(String s);
}
class App {
void fooBar() {
Foo foo = s -> {};
}
}
return keyword must be omitted as well@FunctionalInterface
interface Foo {
void foo(String s);
}
@FunctionalInterface
interface Bar {
int bar(String s);
}
class App {
void fooBar() {
Foo foo = s -> System.out.println(s);
Bar bar = s -> -1; // return -1;
}
}
null or chained method calls are fine when curly braces are omitted@FunctionalInterface
interface Foo {
void foo(String s);
}
@FunctionalInterface
interface Bar {
Integer bar(String s);
}
class App {
void fooBar() {
Foo foo = s -> new StringBuilder().append(s).append(s).append(s);
Bar bar = s -> null; // return null;
}
}
@FunctionalInterface
interface Foo {
Integer foo(int i);
}
class App {
void foo() {
Foo foo = i -> Math.abs(i); // return Math.abs(i);
}
}
Runnable r = () -> {}; // Runnable here is the Target Type
new Thread(() -> {});
Runnable r = () -> {};
Runnable runnable() {
return () -> {};
}
Runnable r = aBoolean ? () -> {} : () -> {};
Supplier<Runnable> runnableSupplier = () -> () -> {};
Object o = (Runnable) () -> {};
Runnable[] arr = new Runnable[]{() -> {}, () -> {}};
@FunctionalInterface
interface Foo {
int FOO_CONST = -1;
int foo();
}
class FooTest {
void fooTest() {
// Not allowed: Foo foo = () -> {return FOO_CONST;};
Foo foo = () -> Foo.FOO_CONST;
}
}
@FunctionalInterface
interface Foo {
int foo(int i);
}
class FooTest {
void fooTest() {
int i = -1;
// Not allowed: Foo foo = (i) -> -1;
// Not allowed: Foo foo = (k) -> {int i = -5; return k;};
// This is fine:
Foo foo = (k) -> {k = 10; return k;};
}
}
@FunctionalInterface
interface Foo {
int foo();
}
class FooTest {
int i = -1;
void fooTest() {
// Shadows the instance field i, returns 10 not -1:
Foo foo = () -> {
int i = 10;
return i;
};
}
}
this refers to enclosing object@FunctionalInterface
interface Foo {
int foo();
}
class FooTest {
int i = -1;
void fooTest() {
Foo foo = () -> {
int i = 1;
return this.i; // returns -1, not 1!
};
}
}
import java.util.function.IntSupplier;
class Foo {
private int foo() {
return 42;
}
public int bar() {
// Compiles fine
return ((IntSupplier) () -> foo()).getAsInt();
}
}
// aLong here is effectively final, this code compiles fine
long aLong = 1L;
LongUnaryOperator op = l -> aLong;
long anotherLong = 1L;
anotherLong = 2L; // not effectively final!
// This code will not compile
// LongUnaryOperator op = l -> anotherLong;
void foo() {
int i = 10;
// Will not compile since i is modified
// IntSupplier is = () -> i++;
}
class Foo {
int i;
void foo() {
// fine since i is an instance variable
IntSupplier is = () -> i++;
}
}
class Foo {
final int i = -1;
void foo() {
// will not compile
// IntSupplier is = () -> i++;
}
}
If the body of the lambda is a statement expression, the lambda can still be assigned to a Functional Interface that has a void return type, even if the statement expression has a return type.
// Single Abstract Method in the Consumer interface is `void accept(T t)`
// Boolean.valueOf(true) actually returns a Boolean object
// However the following compiles fine according to the above rule mentioned
Consumer<Integer> ic = i -> Boolean.valueOf(true);
// This does not compile:
// Consumer<Integer> ic = i -> {return Boolean.valueOf(true);};
// This does not compile either:
// Consumer<Integer> ic = i -> true;
// This does not compile either, you get the idea..
// Consumer<Integer> ic = i -> 1 == 1;
import java.util.function.IntUnaryOperator;
class Factorial {
IntUnaryOperator fact;
Factorial() {
fact = i -> {
if (i == 0) {
return 1;
} else {
return i * fact.applyAsInt(i - 1);
}
};
}
public static void main(String[] args) {
final Factorial factorial = new Factorial();
System.out.println(factorial.fact.applyAsInt(5)); // 120
}
}