【Java8新特性】函數(shù)式接口、默認方法和 Optional 類

一、函數(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類深度解析

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 國家電網(wǎng)公司企業(yè)標準(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 12,307評論 6 13
  • Java8 in action 沒有共享的可變數(shù)據(jù),將方法和函數(shù)即代碼傳遞給其他方法的能力就是我們平常所說的函數(shù)式...
    鐵牛很鐵閱讀 1,357評論 1 2
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評論 19 139
  • 原鏈接:http://www.cnblogs.com/langtianya/p/3757993.html JDK各...
    把愛放下會走更遠閱讀 1,210評論 0 10
  • 首先感謝簡書這個平臺給廣大簡友們提供了這么好的閱讀機會,免費送你一本書,你只需要在收到書后兩周內(nèi)寫一篇書評。 其次...
    周小北baby閱讀 974評論 22 26

友情鏈接更多精彩內(nèi)容