Overview
Java Lambda implemented in version 8 is a function that a definition of a method can be described as an expression.
Before Java8
Programmers must have implemented an interface to pass logic codes.
public class Main {
interface IGreeter {
void greet(String name);
}
static void delegate(IGreeter iGreeter, String name){
iGreeter.greet(name);
}
public static void main(String[] args) throws Exception {
// need to put an object implemented the interface 'IGreeter'
delegate(new IGreeter(){
public void greet(String name){
System.out.println("Hello, " + name + "."); // => Hello, Taro.
}
}, "Taro");
}
}
From Java8
That can be written simpler than before, and it increased the readability for programmers.
public class Main {
interface IGreeter {
void greet(String name);
}
static void delegate(IGreeter iGreeter, String name){
iGreeter.greet(name);
}
public static void main(String[] args) throws Exception {
// The below callings print 'Hello, Taro.'
delegate((name) -> {System.out.println("Hello, " + name + ".");}, "Taro"); // (arg) -> {sentences}
delegate(name -> {System.out.println("Hello, " + name + ".");}, "Taro"); // arg -> {sentences} #if only having one arg, it can omit ()
delegate(name -> System.out.println("Hello, " + name + "."), "Taro"); // arg -> expression
}
}
"This" reference
Between a Lambda method and an anonymous interface, the meanings of "this" reference are different, be careful.
public class Main {
private final String value = "aaa";
interface IPrinter {
void printValue();
}
void delegate(IPrinter iPrinter){
iPrinter.printValue();
}
void callDelegate(){
delegate(() -> System.out.println("value => " + this.value)); // value => aaa
}
public static void main(String[] args) throws Exception {
// 1) Lambda expression
new Main().callDelegate();
// 2) Anonymous interface
new Main().delegate(new IPrinter(){
private final String value = "bbb";
public void printValue(){
System.out.println("value => " + this.value); // value => bbb
}
});
}
}
Accessible variables
From Lambda expression, Substantially 'final' variables can be accessed.
Even without 'final' keyword, if the value is not changed, it is accessible.
public class Main {
interface IPrinter {
void printValue();
}
static void delegate(IPrinter iPrinter){
iPrinter.printValue();
}
public static void main(String[] args) throws Exception {
int aaa = 100;
delegate(() -> System.out.println(aaa)); // 100
//aaa = 200;
//If the above sentence is uncommented, a compile error will occur with the below error message.
//Main.java:14: error: local variables referenced from a lambda expression must be final or effectively final
}
}
Stateful Lambda expression
If you would like to have a Lambda expression with state, there are two ways.
1) Use instance field
public class Main {
interface ICounter {
int nextValue();
}
private int count; // the default value is zero
ICounter makeCounter(){
return () -> count++;
}
public static void main(String[] args) throws Exception {
ICounter iCounter = new Main().makeCounter();
System.out.println(iCounter.nextValue()); // 0
System.out.println(iCounter.nextValue()); // 1
System.out.println(iCounter.nextValue()); // 2
}
}
2) Use referred object
public class Main {
interface ICounter {
int nextValue();
}
private int count; // the default value is zero
ICounter makeCounter(){
// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicInteger.html
AtomicInteger count = new AtomicInteger();
return () -> count.getAndIncrement();
}
public static void main(String[] args) throws Exception {
ICounter iCounter = new Main().makeCounter();
System.out.println(iCounter.nextValue()); // 0
System.out.println(iCounter.nextValue()); // 1
System.out.println(iCounter.nextValue()); // 2
}
}
Reference
改訂2版 パーフェクトJava
https://gihyo.jp/book/2014/978-4-7741-6685-8
Top comments (0)