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");
}
}
Enter fullscreen mode Exit fullscreen mode
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
}
}
Enter fullscreen mode Exit fullscreen mode
“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
}
});
}
}
Enter fullscreen mode Exit fullscreen mode
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
}
}
Enter fullscreen mode Exit fullscreen mode
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
}
}
Enter fullscreen mode Exit fullscreen mode
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
}
}
Enter fullscreen mode Exit fullscreen mode
Reference
改訂2版 パーフェクトJava
https://gihyo.jp/book/2014/978-4-7741-6685-8
暂无评论内容