Java 8 新特性

摘抄自 菜鳥(niǎo)教程 Java 8 新特性

Java 8 (又稱(chēng)為 jdk 1.8) 是 Java 語(yǔ)言開(kāi)發(fā)的一個(gè)主要版本。 Oracle 公司于 2014 年 3 月 18 日發(fā)布 Java 8 ,它支持函數(shù)式編程,新的 JavaScript 引擎,新的日期 API,新的 Stream API 等。

一、新特性

Java 8 新增了非常多的特性,我們主要討論以下幾個(gè):

1. Lambda 表達(dá)式

Lambda 表達(dá)式,也可稱(chēng)為閉包,它是推動(dòng) Java 8 發(fā)布的最重要新特性。Lambda 允許把函數(shù)作為一個(gè)方法的參數(shù)(函數(shù)作為參數(shù)傳遞進(jìn)方法中)。使用 Lambda 表達(dá)式可以使代碼變的更加簡(jiǎn)潔緊湊。

Lambda 表達(dá)式的語(yǔ)法格式如下:
(parameters) -> expression
或
(parameters) ->{ statements; }
以下是 Lambda 表達(dá)式的重要特征:
  • 可選類(lèi)型聲明:不需要聲明參數(shù)類(lèi)型,編譯器可以統(tǒng)一識(shí)別參數(shù)值。

  • 可選的參數(shù)圓括號(hào):一個(gè)參數(shù)無(wú)需定義圓括號(hào),但多個(gè)參數(shù)需要定義圓括號(hào)。

  • 可選的大括號(hào):如果主體包含了一個(gè)語(yǔ)句,就不需要使用大括號(hào)。

  • 可選的返回關(guān)鍵字:如果主體只有一個(gè)表達(dá)式返回值則編譯器會(huì)自動(dòng)返回值,大括號(hào)需要指定明表達(dá)式返回了一個(gè)數(shù)值。

Lambda 表達(dá)式的簡(jiǎn)單例子:
// 1. 不需要參數(shù),返回值為 5  
() -> 5  
  
// 2. 接收一個(gè)參數(shù)(數(shù)字類(lèi)型),返回其2倍的值  
x -> 2 * x  
  
// 3. 接受2個(gè)參數(shù)(數(shù)字),并返回他們的差值  
(x, y) -> x – y  
  
// 4. 接收2個(gè)int型整數(shù),返回他們的和  
(int x, int y) -> x + y  
  
// 5. 接受一個(gè) string 對(duì)象,并在控制臺(tái)打印,不返回任何值(看起來(lái)像是返回void)  
(String s) -> System.out.print(s)

2. 方法引用

方法引用提供了非常有用的語(yǔ)法,可以直接引用已有 Java 類(lèi)或?qū)ο螅▽?shí)例)的方法或構(gòu)造器。與 lambda 聯(lián)合使用,方法引用可以使語(yǔ)言的構(gòu)造更緊湊簡(jiǎn)潔,減少冗余代碼。

方法引用通過(guò)方法的名字來(lái)指向一個(gè)方法。方法引用使用一對(duì)冒號(hào) :: 。

下面,我們?cè)?Car 類(lèi)中定義了 4 個(gè)方法作為例子來(lái)區(qū)分 Java 中 4 種不同方法的引用。

package com.runoob.main;
 
@FunctionalInterface
public interface Supplier<T> {
    T get();
}
 
class Car {
    //Supplier是jdk1.8的接口,這里和lamda一起使用了
    public static Car create(final Supplier<Car> supplier) {
        return supplier.get();
    }
 
    public static void collide(final Car car) {
        System.out.println("Collided " + car.toString());
    }
 
    public void follow(final Car another) {
        System.out.println("Following the " + another.toString());
    }
 
    public void repair() {
        System.out.println("Repaired " + this.toString());
    }
}
  • 構(gòu)造器引用:它的語(yǔ)法是 Class::new,或者更一般的 Class< T >::new實(shí)例如下:
final Car car = Car.create( Car::new );
final List< Car > cars = Arrays.asList( car );
  • 靜態(tài)方法引用:它的語(yǔ)法是 Class::static_method,實(shí)例如下:
cars.forEach( Car::collide );
  • 特定類(lèi)的任意對(duì)象的方法引用:它的語(yǔ)法是 Class::method 實(shí)例如下:
cars.forEach( Car::repair );
  • 特定對(duì)象的方法引用:它的語(yǔ)法是 instance::method 實(shí)例如下:
final Car police = Car.create( Car::new );
cars.forEach( police::follow );

3. 函數(shù)式接口

函數(shù)式接口 (Functional Interface) 就是一個(gè)有且僅有一個(gè)抽象方法,但是可以有多個(gè)非抽象方法的接口。函數(shù)式接口可以被隱式轉(zhuǎn)換為 lambda 表達(dá)式。函數(shù)式接口可以讓現(xiàn)有的函數(shù)友好地支持 lambda。

4. 默認(rèn)方法

默認(rèn)方法就是一個(gè)在接口里面有了一個(gè)實(shí)現(xiàn)的方法。

Java 8 默認(rèn)方法

5. 新工具

新的編譯工具,如:Nashorn 引擎 jjs、 類(lèi)依賴(lài)分析器 jdeps。

6. Stream API

新添加的 Stream API(java.util.stream) 把真正的函數(shù)式編程風(fēng)格引入到 Java 中。Java 8 API 添加了一個(gè)新的抽象稱(chēng)為流 Stream,可以讓你以一種聲明的方式處理數(shù)據(jù)。Stream 使用一種類(lèi)似用 SQL 語(yǔ)句從數(shù)據(jù)庫(kù)查詢(xún)數(shù)據(jù)的直觀方式來(lái)提供一種對(duì) Java 集合運(yùn)算和表達(dá)的高階抽象。

這種風(fēng)格將要處理的元素集合看作一種流, 流在管道中傳輸, 并且可以在管道的節(jié)點(diǎn)上進(jìn)行處理, 比如篩選, 排序,聚合等。元素流在管道中經(jīng)過(guò)中間操作(intermediate operation)的處理,最后由最終操作(terminal operation)得到前面處理的結(jié)果。

+--------------------+       +------+   +------+   +---+   +-------+
| stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|
+--------------------+       +------+   +------+   +---+   +-------+

以上的流程轉(zhuǎn)換為 Java 代碼為:

List<Integer> transactionsIds = 
widgets.stream()
             .filter(b -> b.getColor() == RED)
             .sorted((x,y) -> x.getWeight() - y.getWeight())
             .mapToInt(Widget::getWeight)
             .sum();

在 Java 8 中, 集合接口有兩個(gè)方法來(lái)生成流:

  • stream() ? 為集合創(chuàng)建串行流。

  • parallelStream() ? 為集合創(chuàng)建并行流。

List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());

7. Optional 類(lèi)

Optional 類(lèi)是一個(gè)可以為 null 的容器對(duì)象。如果值存在則 isPresent() 方法會(huì)返回 true,調(diào)用 get() 方法會(huì)返回該對(duì)象。

Optional 是個(gè)容器:它可以保存類(lèi)型 T 的值,或者僅僅保存 null。Optional 提供很多有用的方法,這樣我們就不用顯式進(jìn)行空值檢測(cè)。Optional 類(lèi)的引入很好的解決空指針異常。

8. Nashorn, JavaScript 引擎

Java 8 提供了一個(gè)新的 Nashorn javascript 引擎,它允許我們?cè)?JVM 上運(yùn)行特定的 javascript 應(yīng)用。

9. Date Time API

Java 8 日期時(shí)間 API

10. Base 64

在 Java 8 中,Base64 編碼已經(jīng)成為 Java 類(lèi)庫(kù)的標(biāo)準(zhǔn)。Java 8 內(nèi)置了 Base64 編碼的編碼器和解碼器。

Base64 工具類(lèi)提供了一套靜態(tài)方法獲取下面三種 BASE64 編解碼器:

  • 基本:輸出被映射到一組字符 A-Za-z0-9+/,編碼不添加任何行標(biāo),輸出的解碼僅支持 A-Za-z0-9+/。

  • URL:輸出映射到一組字符 A-Za-z0-9+_,輸出是 URL 和文件。

  • MIME:輸出隱射到 MIME 友好格式。輸出每行不超過(guò) 76 字符,并且使用 '\r' 并跟隨 '\n' 作為分割。編碼輸出最后沒(méi)有行分割。

二、編程風(fēng)格

Java 8 希望有自己的編程風(fēng)格,并與 Java 7 區(qū)別開(kāi),以下實(shí)例展示了 Java 7 和 Java 8 的編程格式:

Java8Tester.java 文件代碼:

import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
import java.util.Comparator;
 
public class Java8Tester {
   public static void main(String args[]){
   
      List<String> names1 = new ArrayList<String>();
      names1.add("Google ");
      names1.add("Runoob ");
      names1.add("Taobao ");
      names1.add("Baidu ");
      names1.add("Sina ");
        
      List<String> names2 = new ArrayList<String>();
      names2.add("Google ");
      names2.add("Runoob ");
      names2.add("Taobao ");
      names2.add("Baidu ");
      names2.add("Sina ");
        
      Java8Tester tester = new Java8Tester();
      System.out.println("使用 Java 7 語(yǔ)法: ");
        
      tester.sortUsingJava7(names1);
      System.out.println(names1);
      System.out.println("使用 Java 8 語(yǔ)法: ");
        
      tester.sortUsingJava8(names2);
      System.out.println(names2);
   }
   
   // 使用 java 7 排序
   private void sortUsingJava7(List<String> names){   
      Collections.sort(names, new Comparator<String>() {
         @Override
         public int compare(String s1, String s2) {
            return s1.compareTo(s2);
         }
      });
   }
   
   // 使用 java 8 排序
   private void sortUsingJava8(List<String> names){
      Collections.sort(names, (s1, s2) -> s1.compareTo(s2));
   }
}

執(zhí)行以上腳本,輸出結(jié)果為:

$ javac Java8Tester.java
$ java Java8Tester
使用 Java 7 語(yǔ)法: 
[Baidu , Google , Runoob , Sina , Taobao ]
使用 Java 8 語(yǔ)法: 
[Baidu , Google , Runoob , Sina , Taobao ]
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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