Java 8 新特性

Java 8 新特性

Java 8 (又稱爲 jdk 1.8) 是 Java 語言開發的一個主要版本。 Oracle 公司於 2014 年 3 月 18 日發佈 Java 8 ,它支持函數式編程,新的 JavaScript 引擎,新的日期 API,新的Stream API 等。javascript


0. 新特性

Java8 新增了很是多的特性,咱們主要討論如下幾個:java

  • Lambda 表達式 − Lambda容許把函數做爲一個方法的參數(函數做爲參數傳遞進方法中。
  • 方法引用 − 方法引用提供了很是有用的語法,能夠直接引用已有Java類或對象(實例)的方法或構造器。與lambda聯合使用,方法引用可使語言的構造更緊湊簡潔,減小冗餘代碼。
  • 默認方法 − 默認方法就是一個在接口裏面有了一個實現的方法。
  • 新工具 − 新的編譯工具,如:Nashorn引擎 jjs、 類依賴分析器jdeps。
  • Stream API −新添加的Stream API(java.util.stream) 把真正的函數式編程風格引入到Java中。
  • Date Time API − 增強對日期與時間的處理。
  • Optional 類 − Optional 類已經成爲 Java 8 類庫的一部分,用來解決空指針異常。
  • Nashorn, JavaScript 引擎 − Java 8提供了一個新的Nashorn javascript引擎,它容許咱們在JVM上運行特定的javascript應用。

接下來咱們將詳細爲你們簡介 Java 8 的新特性:程序員

1. Lambda 表達式

Lambda 表達式,也可稱爲閉包,它是推進 Java 8 發佈的最重要新特性。
Lambda 容許把函數做爲一個方法的參數(函數做爲參數傳遞進方法中)。
使用 Lambda 表達式可使代碼變的更加簡潔緊湊。sql

語法

lambda 表達式的語法格式以下:shell

(parameters) -> expression
 或
(parameters) ->{ statements; }

如下是lambda表達式的重要特徵:數據庫

  • 參數能夠是零個或多個
  • 參數類型可指定,可省略(根據表達式上下文推斷)
  • 參數包含在圓括號中,用逗號分隔
  • 表達式主體能夠是零條或多條語句,包含在花括號中
  • 表達式主體只有一條語句時,花括號可省略
  • 表達式主體有一條以上語句時,表達式的返回類型與代碼塊的返回類型一致
  • 表達式只有一條語句時,表達式的返回類型與該語句的返回類型一致
Lambda 表達式實例

Lambda 表達式的簡單例子:express

//零個
() -> System.out.println("no argument");

//一個
x -> x + 1

//兩個
(x,y) -> x + y

//省略參數類型
 View.OnClickListener oneArgument = view -> Log.d(TAG, "one argument");
 //指定參數類型
 View.OnClickListener oneArgument = (View view) -> Log.d(TAG, "one argument");

//多行語句
//返回類型是代碼塊返回的void
View.OnClickListener multiLine = (View view) -> {
      Log.d(TAG,"multi statements");
      Log.d(TAG,"second line");
}

//返回類型是表達式主體語句的返回類型int
(int x)-> x + 1

使用 Lambda 表達式須要注意如下兩點:編程

  • Lambda 表達式主要用來定義行內執行的方法類型接口,例如,一個簡單方法接口。在上面例子中,咱們使用各類類型的Lambda表達式來定義MathOperation接口的方法。而後咱們定義了sayMessage的執行。
  • Lambda 表達式免去了使用匿名方法的麻煩,而且給予Java簡單可是強大的函數化的編程能力。
變量做用域

lambda 表達式只能引用標記了 final 的外層局部變量,這就是說不能在 lambda 內部修改定義在域外的局部變量,不然會編譯錯誤。數組


2. 方法引用

方法引用經過方法的名字來指向一個方法。
方法引用可使語言的構造更緊湊簡潔,減小冗餘代碼。
方法引用使用一對冒號 類名::方法名安全

下面在 Car 類中定義了 4 個方法做爲例子來區分 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());
    }
}
  • 構造器引用:它的語法是Class::new,或者更通常的 Class< T >::new 實例以下:
ClassName::new
  • 靜態方法引用:它的語法是 Class::static_method 實例以下:
ContainingClass::staticMethodName
  • 特定類的任意對象的方法引用:它的語法是 Class::method 實例以下:
ContainingType::methodName
  • 特定對象的方法引用:它的語法是 instance::method 實例以下:
ContainingObject::instanceMethodName

3. 函數式接口

函數式接口(Functional Interface)就是一個有且僅有一個抽象方法,可是能夠有多個非抽象方法的接口。
函數式接口能夠被隱式轉換爲 lambda 表達式。
Lambda 表達式和方法引用(實際上也可認爲是Lambda表達式)上。

如定義了一個函數式接口以下:

@FunctionalInterface
interface GreetingService 
{
    void sayMessage(String message);
}

那麼就可使用Lambda表達式來表示該接口的一個實現(注:JAVA 8 以前通常是用匿名類實現的):

GreetingService greetService1 = message -> System.out.println("Hello " + message);

函數式接口能夠對現有的函數友好地支持 lambda。

JDK 1.8 以前已有的函數式接口:

  • java.lang.Runnable
  • java.util.concurrent.Callable
  • java.security.PrivilegedAction
  • java.util.Comparator
  • java.io.FileFilter
  • java.nio.file.PathMatcher
  • java.lang.reflect.InvocationHandler
  • java.beans.PropertyChangeListener
  • java.awt.event.ActionListener
  • javax.swing.event.ChangeListener

JDK 1.8 新增長的函數接口:

  • java.util.function

java.util.function 包含了不少類,用來支持 Java的 函數式編程,該包中的函數式接口有:

序號 接口 & 描述
1 BiConsumer<T,U> 表明了一個接受兩個輸入參數的操做,而且不返回任何結果
2 BiFunction<T,U,R> 表明了一個接受兩個輸入參數的方法,而且返回一個結果
3 BinaryOperator<T> 表明了一個做用於於兩個同類型操做符的操做,而且返回了操做符同類型的結果
4 BiPredicate<T,U> 表明了一個兩個參數的boolean值方法
5 Boolean Supplier 表明了boolean值結果的提供方
6 Consumer<T> 表明了接受一個輸入參數而且無返回的操做
7 Double BinaryOperator 表明了做用於兩個double值操做符的操做,而且返回了一個double值的結果。
8 Double Consumer 表明一個接受double值參數的操做,而且不返回結果。
9 Double Function<R> 表明接受一個double值參數的方法,而且返回結果
10 Double Predicate 表明一個擁有double值參數的boolean值方法
11 Double Supplier 表明一個double值結構的提供方
12 Double ToIntFunction 接受一個double類型輸入,返回一個int類型結果。
13 Double ToLongFunction 接受一個double類型輸入,返回一個long類型結果
14 Double UnaryOperator 接受一個參數同爲類型double,返回值類型也爲double 。
15 Function<T,R> 接受一個輸入參數,返回一個結果。
16 IntBinaryOperator 接受兩個參數同爲類型int,返回值類型也爲int 。
17 IntConsumer 接受一個int類型的輸入參數,無返回值 。
18 IntFunction<R> 接受一個int類型輸入參數,返回一個結果 。
19 IntPredicate 接受一個int輸入參數,返回一個布爾值的結果。
20 IntSupplier 無參數,返回一個int類型結果。
21 IntToDoubleFunction 接受一個int類型輸入,返回一個double類型結果 。
22 IntToLongFunction 接受一個int類型輸入,返回一個long類型結果。
23 IntUnaryOperator 接受一個參數同爲類型int,返回值類型也爲int 。
24 LongBinaryOperator 接受兩個參數同爲類型long,返回值類型也爲long。
25 LongConsumer 接受一個long類型的輸入參數,無返回值。
26 LongFunction<R> 接受一個long類型輸入參數,返回一個結果。
27 LongPredicate R接受一個long輸入參數,返回一個布爾值類型結果。
28 LongSupplier 無參數,返回一個結果long類型的值。
29 LongToDoubleFunction 接受一個long類型輸入,返回一個double類型結果。
30 LongToIntFunction 接受一個long類型輸入,返回一個int類型結果。
31 LongUnaryOperator 接受一個參數同爲類型long,返回值類型也爲long。
32 ObjDoubleConsumer<T> 接受一個object類型和一個double類型的輸入參數,無返回值。
33 ObjIntConsumer<T> 接受一個object類型和一個int類型的輸入參數,無返回值。
34 ObjLongConsumer<T> 接受一個object類型和一個long類型的輸入參數,無返回值。
35 Predicate<T> 接受一個輸入參數,返回一個布爾值結果。
36 Supplier<T> 無參數,返回一個結果。
37 ToDoubleBiFunction<T,U> 接受兩個輸入參數,返回一個double類型結果
38 ToDoubleFunction<T> 接受一個輸入參數,返回一個double類型結果
39 ToIntBiFunction<T,U> 接受兩個輸入參數,返回一個int類型結果。
40 ToIntFunction<T> 接受一個輸入參數,返回一個int類型結果。
41 ToLongBiFunction<T,U> 接受兩個輸入參數,返回一個long類型結果。
42 ToLongFunction<T> 接受一個輸入參數,返回一個long類型結果。
43 UnaryOperator<T> 接受一個參數爲類型T,返回值類型也爲T。

4. 默認方法

Java 8 新增了接口的默認方法。
簡單說,默認方法就是接口能夠有實現方法,並且不須要實現類去實現其方法。
咱們只需在方法名前面加個default關鍵字便可實現默認方法。

爲何要有這個特性?

首先,以前的接口是個雙刃劍,好處是面向抽象而不是面向具體編程,缺陷是,當須要修改接口時候,須要修改所有實現該接口的類,目前的java 8以前的集合框架沒有foreach方法,一般能想到的解決辦法是在JDK裏給相關的接口添加新的方法及實現。然而,對於已經發布的版本,是無法在給接口添加新方法的同時不影響已有的實現。因此引進的默認方法。他們的目的是爲了解決接口的修改與現有的實現不兼容的問題。

語法

默認方法語法格式以下:

public interface Vehicle {
   default void print(){
      System.out.println("我是一輛車!");
   }
}

多個默認方法

  1. 一個接口有默認方法,考慮這樣的狀況,一個類實現了多個接口,且這些接口有相同的默認方法,如下實例說明了這種狀況的解決方法:
public interface Vehicle {
   default void print(){
      System.out.println("我是一輛車!");
   }
}

public interface FourWheeler {
   default void print(){
      System.out.println("我是一輛四輪車!");
   }
}
  1. 第一個解決方案是建立本身的默認方法,來覆蓋重寫接口的默認方法:
public class Car implements Vehicle, FourWheeler {
   default void print(){
      System.out.println("我是一輛四輪汽車!");
   }
}
  1. 第二種解決方案可使用 super 來調用指定接口的默認方法:
public class Car implements Vehicle, FourWheeler {
   public void print(){
      Vehicle.super.print();
   }
}
靜態默認方法

Java 8 的另外一個特性是接口能夠聲明(而且能夠提供實現)靜態方法。例如:

public interface Vehicle {
   default void print(){
      System.out.println("我是一輛車!");
   }
    // 靜態方法
   static void blowHorn(){
      System.out.println("按喇叭!!!");
   }
}

5. Stream

Java 8 API添加了一個新的抽象稱爲流Stream,可讓你以一種聲明的方式處理數據。
Stream 使用一種相似用 SQL 語句從數據庫查詢數據的直觀方式來提供一種對 Java 集合運算和表達的高階抽象。
Stream API能夠極大提升Java程序員的生產力,讓程序員寫出高效率、乾淨、簡潔的代碼。
這種風格將要處理的元素集合看做一種流, 流在管道中傳輸, 而且能夠在管道的節點上進行處理, 好比篩選, 排序,聚合等。

元素流在管道中通過中間操做(intermediate operation)的處理,最後由最終操做(terminal operation)獲得前面處理的結果。

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

以上的流程轉換爲 Java 代碼爲:

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

Stream(流)是一個來自數據源的元素隊列並支持聚合操做

  • 元素是特定類型的對象,造成一個隊列。 Java中的Stream並不會存儲元素,而是按需計算。
  • 數據源 流的來源。 能夠是集合,數組,I/O channel, 產生器generator 等。
  • 聚合操做 相似SQL語句同樣的操做, 好比filter, map, reduce, find, match, sorted等。

和之前的Collection操做不一樣, Stream操做還有兩個基礎的特徵:

  • Pipelining: 中間操做都會返回流對象自己。 這樣多個操做能夠串聯成一個管道, 如同流式風格(fluent style)。 這樣作能夠對操做進行優化, 好比延遲執行(laziness)和短路( short-circuiting)。
  • 內部迭代: 之前對集合遍歷都是經過Iterator或者For-Each的方式, 顯式的在集合外部進行迭代, 這叫作外部迭代。 Stream提供了內部迭代的方式, 經過訪問者模式(Visitor)實現。
生成流

在 Java 8 中, 集合接口有兩個方法來生成流:

  • stream() − 爲集合建立串行流。
  • parallelStream() − 爲集合建立並行流。
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());

forEach

Stream 提供了新的方法 'forEach' 來迭代流中的每一個數據。如下代碼片斷使用 forEach 輸出了10個隨機數:

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

map

map 方法用於映射每一個元素到對應的結果,如下代碼片斷使用 map 輸出了元素對應的平方數:

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// 獲取對應的平方數
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());

filter

filter 方法用於經過設置的條件過濾出元素。如下代碼片斷使用 filter 方法過濾出空字符串:

List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 獲取空字符串的數量
int count = strings.stream().filter(string -> string.isEmpty()).count();

limit

limit 方法用於獲取指定數量的流。 如下代碼片斷使用 limit 方法打印出 10 條數據:

Random random = new Random();
random.ints().limit(10).forEach(System.out::println);

sorted

sorted 方法用於對流進行排序。如下代碼片斷使用 sorted 方法對輸出的 10 個隨機數進行排序:

Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);

parallel(並行)程序

parallelStream 是流並行處理程序的代替方法。如下實例咱們使用 parallelStream 來輸出空字符串的數量:

List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 獲取空字符串的數量
int count = strings.parallelStream().filter(string -> string.isEmpty()).count();

Collectors

Collectors 類實現了不少歸約操做,例如將流轉換成集合和聚合元素。Collectors 可用於返回列表或字符串:

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

System.out.println("篩選列表: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(","));
System.out.println("合併字符串: " + mergedString);

統計

另外,一些產生統計結果的收集器也很是有用。它們主要用於int、double、long等基本類型上,它們能夠用來產生相似以下的統計結果。

List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);

IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();

System.out.println("列表中最大的數 : " + stats.getMax());
System.out.println("列表中最小的數 : " + stats.getMin());
System.out.println("全部數之和 : " + stats.getSum());
System.out.println("平均數 : " + stats.getAverage());

6. Optional 類

Optional 類是一個能夠爲null的容器對象。若是值存在則isPresent()方法會返回true,調用get()方法會返回該對象。
Optional 是個容器:它能夠保存類型T的值,或者僅僅保存null。Optional提供不少有用的方法,這樣咱們就不用顯式進行空值檢測。
Optional 類的引入很好的解決空指針異常。

類聲明

如下是一個 java.util.Optional<T> 類的聲明:

public final class Optional<T> extends Object
類方法
序號 方法 & 描述
1 static <T> Optional<T> empty() 返回空的 Optional 實例。
2 boolean equals(Object obj) 判斷其餘對象是否等於 Optional。
3 Optional<T> filter(Predicate<? super <T> predicate) 若是值存在,而且這個值匹配給定的 predicate,返回一個Optional用以描述這個值,不然返回一個空的Optional。
4 <U> Optional<U> flatMap(Function<? super T,Optional<U>> mapper) 若是值存在,返回基於Optional包含的映射方法的值,不然返回一個空的Optional。
5 T get() 若是在這個Optional中包含這個值,返回值,不然拋出異常:NoSuchElementException。
6 int hashCode() 返回存在值的哈希碼,若是值不存在 返回 0。
7 void ifPresent(Consumer<? super T> consumer) 若是值存在則使用該值調用 consumer , 不然不作任何事情。
8 boolean isPresent() 若是值存在則方法會返回true,不然返回 false。
9 <U>Optional<U> map(Function<? super T,? extends U> mapper) 若是有值,則對其執行調用映射函數獲得返回值。若是返回值不爲 null,則建立包含映射返回值的Optional做爲map方法返回值,不然返回空Optional。
10 static <T> Optional<T> of(T value) 返回一個指定非null值的Optional。
11 static <T> Optional<T> ofNullable(T value) 若是爲非空,返回 Optional 描述的指定值,不然返回空的 Optional。
12 T orElse(T other) 若是存在該值,返回值, 不然返回 other。
13 T orElseGet(Supplier<? extends T> other) 若是存在該值,返回值, 不然觸發 other,並返回 other 調用的結果。
14 <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) 若是存在該值,返回包含的值,不然拋出由 Supplier 繼承的異常
15 String toString() 返回一個Optional的非空字符串,用來調試

[注意]這些方法是從 java.lang.Object 類繼承來的。


7. Nashorn, JavaScript 引擎

Nashorn 一個 javascript 引擎。
從JDK 1.8開始,Nashorn取代Rhino(JDK 1.6, JDK1.7)成爲Java的嵌入式JavaScript引擎。Nashorn徹底支持ECMAScript 5.1規範以及一些擴展。它使用基於JSR 292的新語言特性,其中包含在JDK 7中引入的 invokedynamic,將JavaScript編譯成Java字節碼。
與先前的Rhino實現相比,這帶來了2到10倍的性能提高。

jjs

jjs是個基於Nashorn引擎的命令行工具。它接受一些JavaScript源代碼爲參數,而且執行這些源代碼。

例如,咱們建立一個具備以下內容的sample.js文件:

print('Hello World!');

打開控制檯,輸入如下命令:

$ jjs sample.js

以上程序輸出結果爲:

Hello World!

jjs 交互式編程

打開控制檯,輸入如下命令:

$ jjs
jjs> print("Hello, World!")
Hello, World!
jjs> quit()
>>

傳遞參數

打開控制檯,輸入如下命令:

$ jjs -- a b c
jjs> print('字母: ' +arguments.join(", "))
字母: a, b, c
jjs>
Java 中調用 JavaScript

使用 ScriptEngineManager, JavaScript 代碼能夠在 Java 中執行,實例以下:

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class Java8Tester {
    public static void main(String[] args) {
        ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
        ScriptEngine nashorn = scriptEngineManager.getEngineByName("nashorn");

        String name = "Runoob";
        Integer result = null;

        try {
            nashorn.eval("print('" + name + "')");
            result = (Integer) nashorn.eval("10 + 2");
        } catch (ScriptException e) {
            System.out.println("執行腳本錯誤: " + e.getMessage());
        }

        System.out.println(result.toString());
    }
}

執行以上腳本,輸出結果爲:

$ javac Java8Tester.java 
$ java Java8Tester
Runoob
12
JavaScript 中調用 Java

如下實例演示瞭如何在 JavaScript 中引用 Java 類:

var BigDecimal = Java.type('java.math.BigDecimal');

function calculate(amount, percentage) {

   var result = new BigDecimal(amount).multiply(
   new BigDecimal(percentage)).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_EVEN);

   return result.toPlainString();
}

var result = calculate(568000000000000000023,13.9);
print(result);

咱們使用 jjs 命令執行以上腳本,輸出結果以下:

$ jjs sample.js
78952000000000002017.94

8. 新的日期時間 API

Java 8經過發佈新的Date-Time API (JSR 310)來進一步增強對日期與時間的處理。

在舊版的 Java 中,日期時間 API 存在諸多問題,其中有:

  • 非線程安全 − java.util.Date 是非線程安全的,全部的日期類都是可變的,這是Java日期類最大的問題之一。
  • 設計不好 − Java的日期/時間類的定義並不一致,在java.util和java.sql的包中都有日期類,此外用於格式化和解析的類在java.text包中定義。java.util.Date同時包含日期和時間,而java.sql.Date僅包含日期,將其歸入java.sql包並不合理。另外這兩個類都有相同的名字,這自己就是一個很是糟糕的設計。
  • 時區處理麻煩 − 日期類並不提供國際化,沒有時區支持,所以Java引入了java.util.Calendar和java.util.TimeZone類,但他們一樣存在上述全部的問題。

Java 8 在 java.time 包下提供了不少新的 API。如下爲兩個比較重要的 API:

  • Local(本地) − 簡化了日期時間的處理,沒有時區的問題。
  • Zoned(時區) − 經過制定的時區處理日期時間。

新的java.time包涵蓋了全部處理日期,時間,日期/時間,時區,時刻(instants),過程(during)與時鐘(clock)的操做。

本地化日期時間 API

LocalDate/LocalTime 和 LocalDateTime 類能夠在處理時區不是必須的狀況。

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Month;

public class Java8Tester {
    public static void main(String[] args) {
        Java8Tester java8tester = new Java8Tester();
        java8tester.testLocalDateTime();
    }

    public void testLocalDateTime() {
        // 獲取當前的日期時間
        LocalDateTime currentTime = LocalDateTime.now();
        System.out.println("當前時間: " + currentTime);

        LocalDate date1 = currentTime.toLocalDate();
        System.out.println("date1: " + date1);

        Month month = currentTime.getMonth();
        int day = currentTime.getDayOfMonth();
        int seconds = currentTime.getSecond();

        System.out.println("月: " + month + ", 日: " + day + ", 秒: " + seconds);

        LocalDateTime date2 = currentTime.withDayOfMonth(10).withYear(2012);
        System.out.println("date2: " + date2);

        // 12 december 2014
        LocalDate date3 = LocalDate.of(2014, Month.DECEMBER, 12);
        System.out.println("date3: " + date3);

        // 22 小時 15 分鐘
        LocalTime date4 = LocalTime.of(22, 15);
        System.out.println("date4: " + date4);

        // 解析字符串
        LocalTime date5 = LocalTime.parse("20:15:30");
        System.out.println("date5: " + date5);
    }
}
使用時區的日期時間API

若是咱們須要考慮到時區,就可使用時區的日期時間API:

import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Java8Tester {
    public static void main(String[] args) {
        Java8Tester java8tester = new Java8Tester();
        java8tester.testZonedDateTime();
    }

    public void testZonedDateTime() {
        // 獲取當前時間日期
        ZonedDateTime date1 = ZonedDateTime.parse(
                "2015-12-03T10:15:30+05:30[Asia/Shanghai]");
        System.out.println("date1: " + date1);

        ZoneId id = ZoneId.of("Europe/Paris");
        System.out.println("ZoneId: " + id);

        ZoneId currentZone = ZoneId.systemDefault();
        System.out.println("當期時區: " + currentZone);
    }
}

9. Base64

在Java 8中,Base64編碼已經成爲Java類庫的標準。
Java 8 內置了 Base64 編碼的編碼規則和解碼規則。

Base64工具類提供了一套靜態方法獲取下面三種BASE64編解碼對象:

  • 基本:輸出被映射到一組字符A-Za-z0-9+/,編碼不添加任何行標,輸出的解碼僅支持A-Za-z0-9+/。 URL:輸出映射到一組字符A-Za-z0-9+_,輸出是URL和文件。
  • MIME:輸出隱射到MIME友好格式。輸出每行不超過76字符,而且使用'\r'並跟隨'\n'做爲分割。編碼輸出最後沒有行分割。
內嵌類
序號 內嵌類 & 描述
1 static class Base64.Decoder 該類實現一個解碼對象用於,使用 Base64 編碼來解碼字節數據。
2 static class Base64.Encoder 該類實現一個編碼對象,使用 Base64 編碼來編碼字節數據。
方法
序號 方法名 & 描述
1 static Base64.Decoder getDecoder() 返回一個 Base64.Decoder ,解碼使用基本型 base64 編碼方案。
2 static Base64.Encoder getEncoder() 返回一個 Base64.Encoder ,編碼使用基本型 base64 編碼方案。
3 static Base64.Decoder getMimeDecoder() 返回一個 Base64.Decoder ,解碼使用 MIME 型 base64 編碼方案。
4 static Base64.Encoder getMimeEncoder() 返回一個 Base64.Encoder ,編碼使用 MIME 型 base64 編碼方案。
5 static Base64.Encoder getMimeEncoder(int lineLength, byte[] lineSeparator) 返回一個 Base64.Encoder ,編碼使用 MIME 型 base64 編碼方案,能夠經過參數指定每行的長度及行的分隔符。
6 static Base64.Decoder getUrlDecoder() 返回一個 Base64.Decoder ,解碼使用 URL 和文件名安全型 base64 編碼方案。
7 static Base64.Encoder getUrlEncoder() 返回一個 Base64.Encoder ,編碼使用 URL 和文件名安全型 base64 編碼方案。

[注意]Base64 類的不少方法從 java.lang.Object 類繼承。

相關文章
相關標籤/搜索