一、函數(shù)式接口
函數(shù)式接口有一個單一的功能來表現(xiàn)。例如,帶有單個compareTo
方法的比較接口,被用于比較的場合。Java 8 定義了大量的函數(shù)式接口來廣泛地用于lambda表達式。
Java 8 引入的一個核心概念是函數(shù)式接口(Functional Interfaces)。通過在接口里面添加一個抽象方法,這些方法可以直接從接口中運行。如果一個接口定義個唯一一個抽象方法,那么這個接口就成為函數(shù)式接口。同時,引入了一個新的注解:@FunctionalInterface??梢园阉旁谝粋€接口前,表示這個接口是一個函數(shù)式接口。這個注解是非必須的,只要接口只包含一個方法的接口,虛擬機會自動判斷,不過最好在接口上使用注解 @FunctionalInterface 進行聲明。在接口中添加了 @FunctionalInterface 的接口,只允許有一個抽象方法,否則編譯器也會報錯。
1.相關(guān)的接口及描述
下面是部分函數(shù)式接口的列表:
- BitConsumer<T,U>:該接口代表了接收兩個輸入?yún)?shù)T、U,并且沒有返回的操作。
- BiFunction<T,U,R>:該接口代表提供接收兩個參數(shù)T、U,并且產(chǎn)生一個結(jié)果R的方法。
- BinaryOperator<T>:代表了基于兩個相同類型的操作數(shù),產(chǎn)生仍然是相同類型結(jié)果的操作。
- BiPredicate<T,U>:代表了對兩個參數(shù)的斷言操作(基于Boolean值的方法)。
- BooleanSupplier:代表了一個給出Boolean值結(jié)果的方法。
- Consumer<T>:代表了接受單一輸入?yún)?shù)并且沒有返回值的操作。
DoubleBinaryOperator:代表了基于兩個Double類型操作數(shù)的操作,并且返回一個Double類型的返回值。 - DoubleConsumer:代表了一個接受單個Double類型的參數(shù)并且沒有返回的操作。
- DoubleFunction<R>:代表了一個接受Double類型參數(shù)并且返回結(jié)果的方法。
- DoublePredicate:代表了對一個Double類型的參數(shù)的斷言操作。
- DoubleSupplier:代表了一個給出Double類型值的方法。
- DoubleToIntFunction:代表了接受單個Double類型參數(shù)但返回Int類型結(jié)果的方法。
- DoubleToLongFunction:代表了接受單個Double類型參數(shù)但返回Long類型結(jié)果的方法。
- DoubleUnaryOperator:代表了基于單個Double類型操作數(shù)且產(chǎn)生Double類型結(jié)果的操作。
- Function<T,R>:代表了接受一個參數(shù)并且產(chǎn)生一個結(jié)果的方法。
- IntBinaryOperator:代表了對兩個Int類型操作數(shù)的操作,并且產(chǎn)生一個Int類型的結(jié)果。
- IntConsumer:代表了接受單個Int類型參數(shù)的操作,沒有返回結(jié)果。
- IntFunction<R>:代表了接受Int類型參數(shù)并且給出返回值的方法。
- IntPredicate:代表了對單個Int類型參數(shù)的斷言操作。
更多的接口參考Java8官方API手冊:java.lang.Annotation Type FunctionalInterface。在實際使用過程中,加有@FunctionalInterface注解的方法均是此類接口,位于java.util.Funtion包中。
2. 一個函數(shù)式編程的例子
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class NewFeaturesTester {
public static void main(String args[]){
List<Integer> list = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
System.out.println("All of the numbers:");
eval(list, n->true);
System.out.println("Even numbers:");
eval(list, n-> n%2 == 0 );
System.out.println("Numbers that greater than 5:");
eval(list, n -> n > 5 );
}
public static void eval(List<Integer> list, Predicate<Integer> predicate) {
for(Integer n: list) {
if(predicate.test(n)) {
System.out.println(n + " ");
}
}
}
}
二、默認方法
Java 8在接口方面引入了一個關(guān)于默認方法實現(xiàn)的新概念。它也是作為一種向后兼容能力而出現(xiàn),舊的接口也能用到Lambda表達式中。例如,List或Collection接口是沒有forEach方法的聲明的。但是,通過這些默認方法能夠就能輕易地打破集合框架實現(xiàn)的限制。Java 8引入默認方式使得List和Collection接口能夠擁有forEach方法的默認實現(xiàn)。實現(xiàn)了這些接口的類也不必再實現(xiàn)相同的功能了。
語法如下所示:
public interface boy {
default void print(){
System.out.println("I am a boy.");
}
}
1.多個默認值
接口中有了默認方法之后,在同一個類里面實現(xiàn)兩個帶有相同默認方法的接口就可行了。
首先是同一個類里面的兩個接口。
public interface younger {
default void print(){
System.out.println("I am a younger.");
}
}
public interface learner{
default void print(){
System.out.println("I am a learner.");
}
}
第一個解決辦法就是創(chuàng)建一個自有的方法,來重寫默認的實現(xiàn)。就像這樣:
public class student implements younger, learner {
default void print(){
System.out.println("I am a younger and a learner, so I am a student.");
}
}
另外一個解決辦法是使用超類super來調(diào)用特定接口的默認方法。
public class student implements younger, learner {
default void print(){
learner.super.print();
}
}
2.靜態(tài)默認方法
你也可以為這個接口增加靜態(tài)的輔助方法(helper),就像下面這樣:
public interface Younger {
default void print(){
System.out.println("I am a younger.");
}
static void sayHi(){
System.out.println("Young is the capital.");
}
}
3. 一個默認方法的例子
package com.shiyanlou.java8;
public class NewFeaturesTester {
public static void main(String args[]){
Younger younger = new Student();
younger.print();
}
}
interface Younger {
default void print(){
System.out.println("I am a younger.");
}
static void sayHi(){
System.out.println("Young is the capital.");
}
}
interface Learner {
default void print(){
System.out.println("I am a learner.");
}
}
class Student implements Younger, Learner {
public void print(){
Younger.super.print();
Learner.super.print();
Younger.sayHi();
System.out.println("I am a student!");
}
}
三、Optional類
Optional是一個容器對象,用于容納非空對象。Optional對象通過缺失值值代表null。這個類有許多實用的方法來促使代碼能夠處理一些像可用或者不可用的值,而不是檢查那些空值(null)。Java 8中引入的這個特性有點像Google Guava里的Optional(Guava 是一個 Google 的基于Java 6的類庫集合的擴展項目)。
在Java官方文檔的解釋中,它是一個可以為null的容器對象。如果值存在則isPresent()方法會返回true,調(diào)用get()方法會返回該對象。
1. 類的聲明及方法
下面是java.util.Optional<T>類的聲明:
public final class Optional<T>extends Object
這個類繼承了java.lang.Object類大多數(shù)方法。主要有:
- static <T> Optional<T> empty():該方法返回一個空的Optional實例。
- boolean equals(Object obj):該方法可以指示某個對象是否與當前Optional對象相等。
- Optional<T> filter(Predicate<? super <T> predicate):如果一個值存在并且這個值滿足某個給定的斷言,那么該方法將返回一個描述該值的Optional對象;否則,將返回一個空的Optional對象。
- <U> Optional<U> flatMap(Function<? super T,Optional<U>> mapper):如果一個值存在,該方法會把一個map方法應用于它,并且返回結(jié)果;否則,將返回空的Optional對象。
- T get():如果一個值存在于當前Optional中,則返回這個值;否則將拋出一個NoSuchElementException異常。
- int hashCode():返回當前值的hash編碼值。若這個值不存在,則返回0.
- void ifPresent(Consumer<? super T> consumer):如果一個值存在,該方法會通過該值調(diào)用指定的consumer。如果不存在,則不調(diào)用。
- boolean isPresent():返回一個值是否存在。
- <U>Optional<U> map(Function<? super T,? extends U> mapper:如果一個值存在,則將某個map方法應用于它。如果這個值是非空的,則返回一個描述結(jié)果的Optional對象。
- static <T> Optional<T> of(T value):返回某個存在的非空值的Optional對象。
更多的你可以訪問官方API手冊查看:
http://docs.oracle.com/javase/8/docs/api/java/util/Optional.html
2. 一個Optional類的例子
更多的你可以訪問官package com.shiyanlou.java8;
import java.util.Optional;
public class NewFeaturesTester {
public static void main(String args[]){
NewFeaturesTester tester = new NewFeaturesTester();
Integer value1 = null;
Integer value2 = new Integer(5);
// ofNullable 允許傳參時給出 null
Optional<Integer> a = Optional.ofNullable(value1);
// 如果傳遞的參數(shù)為null,那么 of 將拋出空指針異常(NullPointerException)
Optional<Integer> b = Optional.of(value2);
System.out.println(tester.sum(a,b));
}
public Integer sum(Optional<Integer> a, Optional<Integer> b){
// isPresent 用于檢查值是否存在
System.out.println("First parameter is present: " + a.isPresent());
System.out.println("Second parameter is present: " + b.isPresent());
// 如果當前返回的是傳入的默認值,orElse 將返回它
Integer value1 = a.orElse(new Integer(0));
// get 用于獲得值,條件是這個值必須存在
Integer value2 = b.get();
return value1 + value2;
}
}
Java 8官方教程中對于本節(jié)知識點的講解:
Java SE 8: Lambda Quick Start
The Java Tutorials - Default Methods
擴展閱讀:Java 8 Optional類深度解析