More Related Content Similar to Java8 lambda (20) Java8 lambda4. Java SE 8 新功能
•JSR 308 Annotations on Java Types
•JSR 310 Date and Time API
•JSR 335 Lambda Expressions for the
Java Programming Language
5. Java SE 8 更新
•JSR 114 JDBC Rowsets
•JSR 160 JMX Remote API
•JSR 173 Java Compiler API
•JSR 199 Streaming API for XML
•JSR 221 JDBC 4.0
•JSR 269 Pluggable Annotation-Processing API
9. int highScore = 0;
for (Student student : students) {
if (student.age != 20) {
continue;
}
if (student.score > highScore) {
highScore = student.score;
}
}
13. Anonymous Inner Class
List<String> list = new ArrayList<>();
...
list.stream().sorted(
new Comparator<String>(){
@Override
public void compare(String o1,
String o2) {
return o1.compareTo(o2);
}
});
25. (int x, int y) -> x + y
() -> 42
(String s) -> {
System.out.println(s);
}
•Body is expression
•Body is statement block
26. (String s) ->
System.out.println(s)
•Body is a void method invocation
27. !
(o1, o2) -> {
return o1.compareTo(o2);
}
!
!
!
(o1, o2) -> o1.compareTo(o2)
28. !
(o1, o2) -> {
return o1.compareTo(o2);
}
!
!
!
(o1, o2) -> o1.compareTo(o2)
•lambda 參數名稱不能使用 _ ,被當作保留字
38. •Object 的 public method 不能當唯一的抽
象方法
@FunctionalInterface
interface Hoge {
boolean equals(Object o); // compile error
}
39. •很多時候 lambda expression 只會呼叫一個
方法
(o1, o2) -> o1.compareTo(o2)
!
item -> item.name
!
param -> new Item(param)
Method Reference
43. •Static method
class ItemTool {
static int compareByPrice(Item a,
Item b) {
...
}
}
Arrays.asList(item1,item2,item3)
.sort(ItemTool::compareByPrice);
44. •特定物件的 Instance method
class ItemTool {
int compareByPrice(Item a,
Item b) {
...
}
}
ItemTool tool = new ItemTool();
Arrays.asList(item1,item2,item3)
.sort(tool::compareByPrice);
46. •建構子
<T, R extends Collection<T>>
R copy(List<T> from,
Supplier<R> toFactory){…}
!
List<String> sourceList = ...;
HashSet<String> result =
copy(sourceList, HashSet::new);
47. class Item {
public Item() {…}
public Item(String code) {…}
}
!
interface ItemFactory {
Item create(String code);
}
!
ItemFactory factory = Item::new;
Item item = factory.create("a");
50. Comparator<Item> comparator =
Item::compareByPrice;
!
Comparator<Item> comparator =
itemTool::compareByPrice;
!
Comparator<Item> comparator =
Item::compareTo;
!
Supplier<String> factory =
HashSet::new;
53. •不會製造新的 Scope
•this 是 enclosing class
•沒有 Shadowing 問題
•和 local class 或 anonymous class 不同
int max = 10;
list.stream().filter((s) -> {
int max = 12; // compile error
return s.length() < this.delta
+ max;
});
54. //Outer$1@78308db1
Runnable r1 = new Runnable() {
@Override public void run() {
System.out.println(this);
}
}
!
//Outer@776ec8df
Runnable r2 = () ->
System.out.println(this);
55. •能存取 final & effectively final 的變數
int max = 10;
final int min = 2;
list.stream().filter((s) -> {
max = 12; // compile error
return s.length() < max
&& s.length() > min;
});
max = 15; // compile error
58. (s) -> System.out.println(s)
1. void forEach(Consumer<T>)
2. void onClick(Listener)
Target Typing
•編譯器會依照 lambda expression 的所在場
合或環境的目標型態決定該 lambda
expression 的型態
60. •所以 lambda expression 必須放在編譯器可
以推斷的場合
•Variable declarations
•Assignments
•Return statements
•Array initializers
•Method or constructor arguments
•Lambda expression bodies
•Conditional expressions, ? :
•Cast expressions
61. void invoke(Runnable runnable);
<T> void invoke(Callable<T> callable);
// Callable<Integer>
invoke(() -> 3);
// Runnable
invoke(() -> System.out.println(3));
// ???
invoke(() -> {
while(true){ … }
});
62. void invoke(Runnable runnable);
<T> void invoke(Callable<T> callable);
// Callable<Integer>
invoke(() -> 3);
// Runnable
invoke(() -> System.out.println(3));
// ???
invoke((Runnable)() -> {
while(true){ … }
});
63. 型推論的強化
•Java 7 的 <>
◎ List<Integer> l1 = new ArrayList<>();
❌ List<Number> l2 = new ArrayList<>(1,
2);
❌ calculate(new ArrayList<>());
❌ List<String> result = a == 10
? new ArrayList<>()
: Collections.emptyList();
64. •Java 8 的 <>
◎ List<Integer> ages = new ArrayList<>();
◎ List<Number> l2 = new ArrayList<>(1,
2);
◎ calculate(new ArrayList<>());
◎ List<String> result = a == 10
? new ArrayList<>()
: Collections.emptyList();
66. •Java 8 新增了 Default Methods
•就算新增方法也能保持相容性
•實作在 interface 且會是 public 方法
•當實作類別沒有實作時會使用此預設方法
interface Foo{
…
default int sum(int a, int b){
return a + b;
}
}
74. Static interface method
•在 interface 中定義 static method
interface Foo{
static int sum(int a, int b){
return a + b;
}
}
Foo.sum(1, 2);
75. •不能繼承,只能透過定義的 interface 呼叫
•此點和類別中的 static method 不同
interface Bar extends Foo{
}
Bar.sum(1, 2); // compile error!!
!
class Hoge implements Foo{
}
Hoge.sum(1, 2); // compile error!!
83. public static void main(String[] args) {
Runnable r = () -> {
try {
Object o = null;
o.getClass();
throw new IOException();
} catch(IOException | IllegalArgumentException e) {
System.out.println("KO !");
} catch(RuntimeException e) {
System.out.println("OK !");
}
};
r.run();
}
http://mail.openjdk.java.net/pipermail/lambda-dev/2014-March/011940.html
84. Function<Integer, Integer> s1 = new
Function<Integer, Integer>() {
@Override public Integer apply(Integer
t) {
return t++;
}
};
Function<Integer, Integer> s2 = (t) -> t++;
!
System.out.println(s1.apply(2)); // 2
System.out.println(s2.apply(2)); // 3
https://bugs.openjdk.java.net/browse/JDK-8038420
87. Lambda is Inner Class ?
•看來只要用 inner class 就可以實作了?
class Hoge$1 implements Consumer<String>{
private final Logger logger;
Hoge$1(Logger logger){
this.logger = logger;
}
@Override
public void accept(String t){
logger.log(t);
}
}
89. Why not ?
•一個 lambda expression 要一個類別
•一開始就選死方法,未來如果有新實作方式該
怎麼辦 ?
90. MethodHandle
•與 invokedynamic 一起從 JSR-292
(Java 7 )新增
•java.util.invoke
•A reference to method(or field,
constructor or other bit of functionality)
that can be executed
98. Client
Bootstrap CallSite
MethodHandle Target Method
MethodHandles.Lookup lookup = MethodHandles.lookup();
return new ConstantCallSite(
lookup.findStatic(Hoge.class, "printArgs",
MethodType
.methodType(void.class, Object[].class)
.asType(type));
99. 透過 indy 轉換 lambda
•將 lambda 轉換成和 functional interface
相同 signature 的方法(依情況爲靜態或非靜
態)
item -> item.getPrice() > 10
!
private static boolean lambda$1(Item item)
{
return item.getPrice() > 10;
}
100. •產生 indy call site,呼叫時回傳 lambda,
也就是 lambda factory
item -> item.getPrice() > 10
!
!
Predicate $p =
indy[bootstrap=LambdaMetafactory,
staticargs=[Predicate, lambda$1])
stream.filter($p);
102. 轉換策略
•Runtime 時產生 inner class
•就像之前編譯器產生的一樣,裡面透過
invokestatic 和 invokevirtual 直接呼叫 lambda
產生的方法
•Runtime 時依照 interface 建立 wrapper class
•建構子傳入MH
•Dynamic proxies or MH proxy
•VM private api, or ...