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
}
}