3分鐘看完Java 8——史上最強Java 8新特性總結之第四篇 其餘新特性

目錄

· 默認方法和靜態方法java

    · 初步理解程序員

    · 應用模式編程

    · 優先級問題安全

· Optional網絡

· CompletableFuture併發

    · 基本用法app

    · CompletableFuture與Stream API框架

· 新日期和時間APIdom

    · 舊API異步

    · 建立

    · 操做

    · 格式化與解析

    · 時區


 

默認方法和靜態方法

初步理解

1. 面臨問題:Java 8之前,當已設計的接口被其餘框架、庫使用後,若是向接口添加新方法,將致使這些框架和庫沒法編譯。

2. 解決方法:Java 8可在接口中使用靜態方法和默認方法。

應用模式

1. 合併接口與輔助工具類:好比接口java.util.Collection與其輔助工具類java.util.Collections,接口支持靜態方法後,可將輔助工具類的方法加入到接口。

2. 可選方法:好比JDK中的java.util.Iterator,接口提供一個默認的remove()實現,這樣實體類就無需在本身的實現中顯式地提供一個空方法。

 1 interface Iterator<T> {
 2 
 3     boolean hasNext();
 4 
 5     T next();
 6 
 7     default void remove() {
 8         throw new UnsupportedOperationException();
 9     }
10 
11 }

3. 行爲多繼承

    a) Rotatable.java

 1 public interface Rotatable {
 2 
 3     void setRotationAngle(int angleInDegrees);
 4 
 5     int getRotationAngle();
 6 
 7     default void rotateBy(int angleInDegrees) {
 8         setRotationAngle((getRotationAngle() + angleInDegrees) % 360);
 9     }
10 
11 }

    b) Moveable.java

 

 1 public interface Moveable {
 2 
 3     int getX();
 4 
 5     int getY();
 6 
 7     void setX(int x);
 8 
 9     void setY(int y);
10 
11     default void moveHorizontally(int distance) {
12         setX(getX() + distance);
13     }
14 
15     default void moveVertically(int distance) {
16         setY(getY() + distance);
17     }
18 
19 }

    c) Resizable.java

 1 public interface Resizable {
 2 
 3     int getWidth();
 4 
 5     int getHeight();
 6 
 7     void setWidth(int width);
 8 
 9     void setHeight(int height);
10 
11     void setAbsoluteSize(int width, int height);
12 
13     default void setRelativeSize(int wFactor, int hFactor) {
14         setAbsoluteSize(getWidth() / wFactor, getHeight() / hFactor);
15     }
16 
17 }

    d) Monster.java

 1 public class Monster implements Rotatable, Moveable, Resizable {
 2 
 3     @Override
 4     public int getX() {
 5         return 0;
 6     }
 7 
 8     @Override
 9     public int getY() {
10         return 0;
11     }
12 
13     @Override
14     public void setX(int x) {
15     }
16 
17     @Override
18     public void setY(int y) {
19 
20     }
21 
22     @Override
23     public int getWidth() {
24         return 0;
25     }
26 
27     @Override
28     public int getHeight() {
29         return 0;
30     }
31 
32     @Override
33     public void setWidth(int width) {
34     }
35 
36     @Override
37     public void setHeight(int height) {
38     }
39 
40     @Override
41     public void setAbsoluteSize(int width, int height) {
42     }
43 
44     @Override
45     public void setRotationAngle(int angleInDegrees) {
46     }
47 
48     @Override
49     public int getRotationAngle() {
50         return 0;
51     }
52 
53 }

    e) Sun.java

 1 public class Sun implements Moveable, Rotatable {
 2 
 3     @Override
 4     public int getX() {
 5         return 0;
 6     }
 7 
 8     @Override
 9     public int getY() {
10         return 0;
11     }
12 
13     @Override
14     public void setX(int x) {
15     }
16 
17     @Override
18     public void setY(int y) {
19     }
20 
21     @Override
22     public void setRotationAngle(int angleInDegrees) {
23     }
24 
25     @Override
26     public int getRotationAngle() {
27         return 0;
28     }
29 
30 }

優先級問題

1. 方法執行優先級規則:

    a) 距離當前類越近的方法優先級越高;

    b) 顯示方法近於隱式方法;

    c) 距離相等時,非默認方法優先於默認方法。

2. 舉例

    a) hello()方法優先級:B > A。

        i. A.java

1 public interface A {
2     
3     default void hello() {
4         System.out.println("Hello from A");
5     }
6     
7 }

        ii. B.java

1 public interface B extends A {
2 
3     default void hello() {
4         System.out.println("Hello from B");
5     }
6 
7 }

        iii. C.java

1 public class C implements B, A {
2 
3     public static void main(String[] args) {
4         new C().hello(); // Hello from B
5     }
6 
7 }

    b) hello()方法優先級:B > A。

        i. A.java

1 public interface A {
2     
3     default void hello() {
4         System.out.println("Hello from A");
5     }
6     
7 }

        ii. B.java

1 public interface B extends A {
2 
3     default void hello() {
4         System.out.println("Hello from B");
5     }
6 
7 }

        iii. D.java

1 public class D implements A{
2 }

        iv. C.java

1 public class C extends D implements B, A {
2 
3     public static void main(String[] args) {
4         new C().hello(); // Hello from B
5     }
6 
7 }

    c) hello()方法優先級:D > B > A。

        i. A.java

1 public interface A {
2     
3     default void hello() {
4         System.out.println("Hello from A");
5     }
6     
7 }

        ii. B.java

1 public interface B extends A {
2 
3     default void hello() {
4         System.out.println("Hello from B");
5     }
6 
7 }

        iii. D.java

1 public class D implements A {
2 
3     @Override
4     public void hello() {
5         System.out.println("Hello from D");
6     }
7 
8 }

        iv. C.java

1 public class C extends D implements B, A {
2 
3     public static void main(String[] args) {
4         new C().hello(); // Hello from D
5     }
6 
7 }

    d) hello()方法優先級:C > B = A,因爲A、B優先級相等,有衝突,因此必須在C中Override hello()方法,不然將報錯class C inherits unrelated defaults for hello() from types B and A。

        i. A.java

1 public interface A {
2     
3     default void hello() {
4         System.out.println("Hello from A");
5     }
6     
7 }

        ii. B.java

1 public interface B {
2 
3     default void hello() {
4         System.out.println("Hello from B");
5     }
6 
7 }

        iii. C.java 

 1 public class C implements B, A {
 2 
 3     @Override
 4     public void hello() {
 5         B.super.hello();
 6     }
 7 
 8     public static void main(String[] args) {
 9         new C().hello(); // Hello from B
10     }
11 
12 }

Optional

1. Optional目的:解決null帶來的如下問題。

    a) 錯誤:NullPointerException。

    b) 代碼膨脹:代碼充斥着深度嵌套的null檢查,可讀性變差。

    c) 毫無心義:null自身沒有任何語義,它表明在靜態類型語言中以一種錯誤的方式對缺失變量值的建模。

    d) 破壞了Java的哲學:Java一直試圖避免讓程序員意識到指針的存在,惟一的例外是null指針。

    e) 類型缺陷:null並不屬於任何類型,它能夠被賦值給任意引用類型的變量。這致使當這個變量被傳遞到系統中的另外一個部分後,將沒法獲知null變量最初的賦值究竟是什麼類型。

2. java.util.Optional類的方法

方法

描述

empty

返回空Optional實例

filter

若是值存在而且知足提供的Predicate,則返回包含該值的Optional對象;不然返回空Optional對象

flatMap

若是值存在,就對該值執行提供的mapping函數,返回Optional類型的值,不然返回一個空Optional對象

get

若是值存在,將該值用Optional封裝返回,不然拋出NoSuchElementException異常

ifPresent

若是值存在,則執行使用該值的方法調用,不然什麼也不作

isPresent

若是值存在,則返回true,不然返回false

map

若是值存在,則對該值執行提供的mapping函數

of

將指定值用Optional封裝後返回,若是該值爲null,則拋出NullPointerException異常

ofNullable

將指定值用Optional封裝後返回,若是該值爲null,則返回空Optional對象

orElse

若是有值,則將其返回,不然返回一個默認值

orElseGet

若是有值,則將其返回,不然返回由指定Supplier接口生成的值

orElseThrow

若是有值,則將其返回,不然拋出指定的Supplier接口生成的異常

3.舉例

    a) 使用Optional前

        i. Person.java

1 public class Person {
2 
3     private Car car;
4 
5     public Car getCar() {
6         return car;
7     }
8 
9 }

        ii. Car.java

1 public class Car {
2 
3     private Insurance insurance;
4 
5     public Insurance getInsurance() {
6         return insurance;
7     }
8 
9 }

        iii. Insurance.java

1 public class Insurance {
2 
3     private String name;
4 
5     public String getName() {
6         return name;
7     }
8 
9 }

        iv. Test.java

 1 public class Test {
 2 
 3     public static String getCarInsuranceName(Person person) {
 4         if (person != null) {
 5             Car car = person.getCar();
 6             if (car != null) {
 7                 Insurance insurance = car.getInsurance();
 8                 if (insurance != null) {
 9                     return insurance.getName();
10                 }
11             }
12         }
13         return "Unknown";
14     }
15 
16 }

    b) 使用Optional後

        i. Person.java

 1 import java.util.Optional;
 2 
 3 public class Person {
 4 
 5     // 可能爲null
 6     private Car car;
 7 
 8 public Optional<Car> getCar() {
 9         // 使用Optional封裝car,容許car爲null
10         return Optional.ofNullable(car);
11     }
12 
13 }

        ii. Car.java

 1 import java.util.Optional;
 2 
 3 public class Car {
 4 
 5     // 可能爲null
 6     private Insurance insurance;
 7 
 8     public Optional<Insurance> getInsurance() {
 9         return Optional.ofNullable(insurance);
10     }
11 
12 }

        iii. Insurance.java

 1 public class Insurance {
 2 
 3     // 不可能爲null
 4     private String name;
 5 
 6     // 不可能爲null,因此不使用Optional
 7     public String getName() {
 8         return name;
 9     }
10 
11 }

        iv. Test.java

 1 import java.util.Optional;
 2 
 3 public class Test {
 4 
 5     public static String getCarInsuranceName(Person person) {
 6         Optional<Person> optPerson = Optional.ofNullable(person);
 7         // 因爲Person::getCar返回類型是Optional<Car>,
 8         // 因此optPerson.map(Person::getCar)返回類型是Optional<Optional<Car>>,
 9         // 所以致使map(Car::getInsurance)報錯
10         // Optional<String> name = optPerson.map(Person::getCar)
11         //                 .map(Car::getInsurance)
12         //                 .map(Insurance::getName);
13         // 使用flatMap扁平化,從而避免上述報錯
14         return optPerson.flatMap(Person::getCar)
15                 .flatMap(Car::getInsurance)
16                 .map(Insurance::getName)
17                 .orElse("Unknown"); // 若是Optional結果值爲空,則使用默認值
18     }
19 
20 }

    c) 使用filter()方法判斷Predicate

1 // 不使用Optional
2 Insurance insurance = null;
3 if(insurance != null && "CambridgeInsurance".equals(insurance.getName())){
4     System.out.println("ok");
5 }
6 // 使用Optional
7 Optional<Insurance> optInsurance = Optional.ofNullable(null);
8 optInsurance.filter(ins -> "CambridgeInsurance".equals(ins.getName()))
9         .ifPresent(ins -> System.out.println("ok"));

CompletableFuture

基本用法

1. java.util.concurrent.Future接口

    a) 起始:Java 5。

    b) 使用方法:一般須要將耗時操做封裝在一個Callable對象中,再將它提交給ExecutorService執行,最後經過Future獲取執行結果。

2. java.util.concurrent.CompletableFuture類

    a) 起始:Java 8。

    b) 優勢:比Future更加直觀,功能更強大。

3. 舉例

    a) Future

        i. Shop.java

 

 1 import java.util.concurrent.*;
 2 
 3 public class Shop {
 4 
 5     public double getPrice(String product) {
 6         return calculatePrice(product);
 7     }
 8 
 9     public Future<Double> getPriceAsync(String product) {
10         ExecutorService executor = Executors.newCachedThreadPool();
11         Future<Double> future = executor.submit(new Callable<Double>() {
12             public Double call() {
13                 return getPrice(product);
14             }
15         });
16         return future;
17     }
18 
19     private double calculatePrice(String product) {
20         delay();
21         return Math.random() * 1000;
22     }
23 
24     private static void delay() {
25         try {
26             Thread.sleep(1000L);
27         } catch (InterruptedException e) {
28             throw new RuntimeException(e);
29         }
30     }
31 
32 }

        ii. Test.java

 1 import java.util.concurrent.*;
 2 
 3 public class Test {
 4 
 5     public static void main(String[] args) {
 6         try {
 7             Future<Double> future = new Shop().getPriceAsync("Candy");
 8             Double price = future.get();
 9             System.out.println(price);
10         } catch (InterruptedException e) {
11             e.printStackTrace();
12         } catch (ExecutionException e) {
13             e.printStackTrace();
14         }
15     }
16 
17 }

    b) CompletableFuture方法一

 1 import java.util.concurrent.*;
 2 
 3 public class Shop {
 4 
 5     public double getPrice(String product) {
 6         return calculatePrice(product);
 7     }
 8 
 9     public Future<Double> getPriceAsync(String product) {
10         CompletableFuture<Double> future = new CompletableFuture<>();
11         new Thread(() -> {
12             try {
13                 double price = getPrice(product);
14                 future.complete(price); // 若是價格計算正常結束,完成Future操做並設置商品價格
15             } catch (Exception ex) {
16                 future.completeExceptionally(ex); // 不然就拋出致使失敗的異常,完成此次Future操做
17             }
18         }).start();
19         return future;
20     }
21 
22     private double calculatePrice(String product) {
23         delay();
24         return Math.random() * 1000;
25     }
26 
27     private static void delay() {
28         try {
29             Thread.sleep(1000L);
30         } catch (InterruptedException e) {
31             throw new RuntimeException(e);
32         }
33     }
34 
35 }

    c) CompletableFuture方法二

 1 import java.util.concurrent.*;
 2 
 3 public class Shop {
 4 
 5     public double getPrice(String product) {
 6         return calculatePrice(product);
 7     }
 8 
 9     public Future<Double> getPriceAsync(String product) {
10         return CompletableFuture.supplyAsync(() -> calculatePrice(product));
11     }
12 
13     private double calculatePrice(String product) {
14         delay();
15         return Math.random() * 1000;
16     }
17 
18     private static void delay() {
19         try {
20             Thread.sleep(1000L);
21         } catch (InterruptedException e) {
22             throw new RuntimeException(e);
23         }
24     }
25 
26 }

CompletableFuture與Stream API

1. 並行流與順序流+CompletableFuture均可以實現流的並行處理,如何選取?

    a) 靈活

        i. 並行流:線程數由ForkJoinPool的全局屬性決定。

        ii. 順序流+CompletableFuture:自由建立線程池,靈活控制線程數。

    b) 場景

        i. 並行流:更適合計算密集型而且沒有I/O的操做,由於實現簡單,同時效率更高(若是全部的線程都是計算密集型,則沒有必要建立比CPU核數更多的線程)。

        ii. 順序流+CompletableFuture:更適合並行工做單元涉及I/O等待(包括網絡鏈接等待)的操做,該場景不使用並行流的另外一個緣由是處理流的流水線中若是發生I/O等待,流的延遲特性會讓咱們很難判斷到底何時觸發了等待。該場景線程數用如下公式計算(出自《Java併發編程實戰》):

N threads = N CPU * U CPU * (1 + W/C)

        NCPU爲CPU核數,可經過Runtime.getRuntime().availableProcessors()獲取。

        UCPU爲指望的CPU利用率(應介於0和1之間)。

        W/C是等待時間與計算時間的比率。

2. 舉例

    a) Shop.java

 1 public class Shop {
 2 
 3     private String name;
 4 
 5     public Shop(String name) {
 6         this.name = name;
 7     }
 8 
 9     public String getName() {
10         return name;
11     }
12 
13     public double getPrice(String product) {
14         return calculatePrice(product);
15     }
16 
17     private double calculatePrice(String product) {
18         delay();
19         return Math.random() * 1000;
20     }
21 
22     private static void delay() {
23         try {
24             Thread.sleep(1000L);
25         } catch (InterruptedException e) {
26             throw new RuntimeException(e);
27         }
28     }
29 
30 }

    b) Test.java

 1 import java.util.*;
 2 import java.util.concurrent.*;
 3 
 4 import static java.util.stream.Collectors.toList;
 5 
 6 public class Test {
 7 
 8     // 順序流
 9     public static List<String> findPrices1(List<Shop> shops, String product) {
10         return shops.stream()
11                 .map(shop -> String.format("%s price is %.2f", shop.getName(), shop.getPrice(product)))
12                 .collect(toList());
13     }
14 
15     // 並行流
16     public static List<String> findPrices2(List<Shop> shops, String product) {
17         return shops.parallelStream()
18                 .map(shop -> String.format("%s price is %.2f", shop.getName(), shop.getPrice(product)))
19                 .collect(toList());
20     }
21 
22     // 順序流+CompletableFuture
23     public static List<String> findPrices3(List<Shop> shops, String product) {
24         // 建立一個線程池,線程池中線程的數目爲100和商店數目兩者中較小的一個值
25         Executor executor = Executors.newFixedThreadPool(Math.min(shops.size(), 100),
26                 new ThreadFactory() {
27                     public Thread newThread(Runnable r) {
28                         Thread t = new Thread(r);
29                         t.setDaemon(true); // 使用守護線程——這種方式不會阻止程序的關停
30                         return t;
31                     }
32                 });
33         List<CompletableFuture<String>> priceFutures = shops.stream()
34                 .map(shop -> CompletableFuture.supplyAsync(() -> String.format("%s price is %.2f", shop.getName(), shop.getPrice(product)), executor))
35                 .collect(toList());
36         return priceFutures.stream()
37                 .map(CompletableFuture::join) // 等待全部異步操做結束
38                 .collect(toList());
39     }
40 
41     public static void printPrices(List<String> prices) {
42         prices.stream().forEach(System.out::println);
43     }
44 
45     public static void main(String[] args) {
46         List<Shop> shops = Arrays.asList(new Shop("BestPrice"),
47                 new Shop("LetsSaveBig"),
48                 new Shop("MyFavoriteShop"),
49                 new Shop("BuyItAll"));
50         String product = "Candy";
51         List<String> prices1 = findPrices1(shops, product);
52         printPrices(prices1);
53         List<String> prices2 = findPrices2(shops, product);
54         printPrices(prices2);
55         List<String> prices3 = findPrices3(shops, product);
56         printPrices(prices3);
57     }
58 
59 }

新日期和時間API

舊API

1. java.util.Date

    a) 起始:Java 1.0。

    b) 缺點:只能以毫秒精度表示時間;易用性差,好比年份從1900開始,月份從0開始。

1 // 2014年3月18日
2 System.out.println(new Date(114, 2, 18));

2.java.util.Calendar

    a) 起始:Java 1.1。

    b) 缺點:易用性差,好比月份從0開始;Date和Calendar如何選擇問題;格式化類DateFormat只能用於Date。

建立

1. java.time.LocalDate

    a) 只存儲年、月、日,不存儲時區。

    b) 不可變,線程安全。

2. java.time.LocalTime

    a) 只存儲時、分、秒,不存儲時區。

    b) 不可變,線程安全。

3. java.time.LocalDateTime

    a) 只存儲年、月、日、時、分、秒,不存儲時區。

    b) 不可變,線程安全。

    c) LocalDate和LocalTime的合體。

4. java.time.Instant

    a) Unix時間戳秒數,即與UTC時區1970-01-01 00:00:00的秒數和納秒差值。

    b) 內部存儲秒數和納秒(1 ns = 10^-9 s)兩個字段。

    c) 面向機器設計的類,方便機器處理。

5. java.time.temporal.ChronoField

    a) 實現了java.time.temporal.TemporalFieldl接口的枚舉,提供了訪問java.time.temporal.Temporal接口實現類的標準字段。

    b) LocalDate、LocalTime、LocalDateTime和Instant實現了Temporal接口。

    c) 注意:因爲Instant是面向機器的,經過ChronoField獲取Instant字段時,只支持秒、毫秒(1,000毫秒=1秒)、微秒(1,000,000微秒=1秒)和納秒(1,000,000,000納秒=1秒)。

6. java.time.Duration

    a) 表示一個時間段的持續時長。

    b) 內部存儲持續時長的秒和納秒。

7. java.time.Period

    a) 表示一個時間段的持續時長。

    b) 內部存儲持續時長的年、月、日。

8. Duration和Period的通用方法

方法

靜態方法

描述

between

Y

建立兩個時間點之間的間隔時長

from

Y

由一個臨時時間點建立間隔時長

of

Y

由組成部分建立時長的實例

parse

Y

由字符串建立時長的實例

addTo

N

建立該時長的副本,並將其疊加到某個指定的Temporal對象

get

N

讀取該時長的狀態

isNegative

N

檢查該時長是否爲負值,不包含零

isZero

N

檢查該時長的時長是否爲零

minus

N

經過減去必定的時間建立該時長的副本

multipliedBy

N

將時長的值乘以某個標量建立該時長的副本

negated

N

以忽略某個時長的方式建立該時長的副本

plus

N

以增長某個指定時長的方式建立該時長的副本

subtractFrom

N

從指定的Temporal對象中減去該時長

9. 舉例

    a) java.time.LocalDate

 1 // 建立
 2 LocalDate today = LocalDate.now();
 3 LocalDate d = LocalDate.parse("2014-03-18");
 4 LocalDate date = LocalDate.of(2014, 3, 18); // 2014-03-18
 5 // 直接獲取字段
 6 int year = date.getYear(); // 2014
 7 Month month = date.getMonth(); // MARCH
 8 int day = date.getDayOfMonth(); // 18
 9 DayOfWeek dow = date.getDayOfWeek(); // TUESDAY
10 int len = date.lengthOfMonth(); // 31 (3月總天數)
11 boolean leap = date.isLeapYear(); // false
12 // 經過ChronoField獲取字段
13 int year = date.get(ChronoField.YEAR); // 2014
14 int month = date.get(ChronoField.MONTH_OF_YEAR); // 3
15 int day = date.get(ChronoField.DAY_OF_MONTH); // 18

    b) java.time.LocalTime

1 // 建立
2 LocalTime t = LocalTime.parse("13:45:20");
3 LocalTime time = LocalTime.of(13, 45, 20); // 13:45:20
4 // 直接獲取字段
5 int hour = time.getHour(); // 13
6 int minute = time.getMinute(); // 45
7 int second = time.getSecond(); // 20

    c) java.time.LocalDateTime

1 // 建立2014-03-18T13:45:20的4種方法
2 LocalDateTime dt1 = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45, 20);
3 LocalDateTime dt2 = LocalDateTime.of(date, time);
4 LocalDateTime dt3 = date.atTime(13, 45, 20);
5 LocalDateTime dt4 = date.atTime(time);
6 // 提取
7 LocalDate date1 = dt1.toLocalDate(); // 2014-03-18
8 LocalTime time1 = dt1.toLocalTime(); // 13:45:20

    d) java.time.Instant

1 // 建立1970-01-01T00:00:03Z的4種方法
2 Object o1 = Instant.ofEpochSecond(3);
3 Object o2 = Instant.ofEpochSecond(3, 0);
4 Object o3 = Instant.ofEpochSecond(2, 1_000_000_000); // 2秒以後再加上100萬納秒(1秒)
5 Object o4 = Instant.ofEpochSecond(4, -1_000_000_000); // 4秒以前的100萬納秒(1秒)
6 // Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: DayOfMonth
7 int day = Instant.now().get(ChronoField.DAY_OF_MONTH);

    e) java.time.Duration

1 // 建立3秒持續時長的5種方法
2 Duration d1 = Duration.between(LocalTime.parse("00:00:00"), LocalTime.parse("00:00:03"));
3 Duration d2 = Duration.between(LocalDateTime.parse("1970-01-01T00:00:00"), LocalDateTime.parse("1970-01-01T00:00:03"));
4 Duration d3 = Duration.between(Instant.ofEpochSecond(0), Instant.ofEpochSecond(3));
5 Duration d4 = Duration.ofSeconds(3);
6 Duration d5 = Duration.of(3, ChronoUnit.SECONDS);

    f) java.time.Period

1 // 建立10天持續時長的3種方法
2 Period p1 = Period.between(LocalDate.of(2014, 3, 8), LocalDate.of(2014, 3, 18));
3 Period p2 = Period.ofDays(10);
4 Period p3 = Period.of(0, 0, 10);

操做

1. 操做相關方法

    a) with*()方法:建立某字段爲新值的新Temporal對象。

    b) plus*()方法:建立加上某個時長的新Temporal對象。

    c) minus*()方法:建立減去某個時長的新Temporal對象。

    d) java.time.temporal.TemporalAdjuster.*方法:高級日期時間操做方法

方法

描述

dayOfWeekInMonth

建立一個新日期,它的值爲同一個月中每一週的第幾天

firstDayOfMonth

建立一個新日期,它的值爲當月的第一天

firstDayOfNextMonth

建立一個新日期,它的值爲下月的第一天

firstDayOfNextYear

建立一個新日期,它的值爲明年的第一天

firstDayOfYear

建立一個新日期,它的值爲當年的第一天

firstInMonth

建立一個新日期,它的值爲同一個月中,第一個符合星期幾要求的值

lastDayOfMonth

建立一個新日期,它的值爲下月的最後一天

lastDayOfNextMonth

建立一個新日期,它的值爲下月的最後一天

lastDayOfNextYear

建立一個新日期,它的值爲明年的最後一天

lastDayOfYear

建立一個新日期,它的值爲今年的最後一天

lastInMonth

建立一個新日期,它的值爲同一個月中,最後一個符合星期幾要求的值

next

previous

建立一個新日期,並將其值設置爲日期調整後或調整前,第一個符合指定星期幾要求的日期

nextOrSame

previousOrSame

建立一個新日期,並將其值設置爲日期調整後或調整前,第一個符合指定星期幾要求的日期,若是該日期已經符合要求,直接返回該對象

2. 舉例

    a) with*()方法

1 LocalDate date1 = LocalDate.of(2014, 3, 18); // 2014-03-18
2 LocalDate date2 = date1.withYear(2011); // 2011-03-18
3 LocalDate date3 = date2.withDayOfMonth(25); // 2011-03-25
4 LocalDate date4 = date3.with(ChronoField.MONTH_OF_YEAR, 9); // 2011-09-25

    b) plus*()方法和minus*()方法

1 LocalDate date1 = LocalDate.of(2014, 3, 18); // 2014-03-18
2 LocalDate date2 = date1.plusWeeks(1); // 2014-03-25
3 LocalDate date3 = date2.minusYears(3); // 2011-03-25
4 LocalDate date4 = date3.plus(6, ChronoUnit.MONTHS); // 2011-09-25

    c) TemporalAdjuster.*方法

1 import static java.time.temporal.TemporalAdjusters.*;
2 LocalDate date1 = LocalDate.of(2014, 3, 18); // 2014-03-18
3 LocalDate date2 = date1.with(nextOrSame(DayOfWeek.SUNDAY)); // 2014-03-23
4 LocalDate date3 = date2.with(lastDayOfMonth()); // 2014-03-31

    d) 自定義TemporalAdjuster:計算下一個工做日(僅跳過週六日)

1 TemporalAdjuster nextWorkingDay = TemporalAdjusters.ofDateAdjuster(
2         temporal -> {
3             DayOfWeek dow = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
4             int dayToAdd = 1;
5             if (dow == DayOfWeek.FRIDAY) dayToAdd = 3;
6             if (dow == DayOfWeek.SATURDAY) dayToAdd = 2;
7             return temporal.plus(dayToAdd, ChronoUnit.DAYS);
8         });
9 date = date.with(nextWorkingDay); // 2014-03-19

格式化與解析

1. java.time.format.DateTimeFormatter

    a) 用於格式化和解析。

    b) 線程安全。

2. 舉例

    a) 使用內置格式格式化與解析

1 // 格式化
2 LocalDate date = LocalDate.of(2014, 3, 18);
3 String s1 = date.format(DateTimeFormatter.BASIC_ISO_DATE); // 20140318
4 String s2 = date.format(DateTimeFormatter.ISO_LOCAL_DATE); // 2014-03-18
5 // 解析
6 LocalDate date1 = LocalDate.parse("20140318", DateTimeFormatter.BASIC_ISO_DATE);
7 LocalDate date2 = LocalDate.parse("2014-03-18", DateTimeFormatter.ISO_LOCAL_DATE);

    b) 使用模式自定義格式式化與解析

1 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
2 // 格式化
3 LocalDate date1 = LocalDate.of(2014, 3, 18);
4 String formattedDate = date1.format(formatter);
5 // 解析
6 LocalDate date2 = LocalDate.parse(formattedDate, formatter);

    c) 更復雜方式自定義格式式化與解析

 1 DateTimeFormatter formatter = new DateTimeFormatterBuilder()
 2         .appendValue(ChronoField.YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
 3         .appendLiteral("年")
 4         .appendValue(ChronoField.MONTH_OF_YEAR, 2)
 5         .appendLiteral("月")
 6         .appendValue(ChronoField.DAY_OF_MONTH, 2)
 7         .appendLiteral("日")
 8         .parseCaseInsensitive()
 9         .toFormatter();
10 // 格式化
11 LocalDate date1 = LocalDate.of(2014, 3, 18);
12 String formattedDate = date1.format(formatter);
13 // 解析
14 LocalDate date2 = LocalDate.parse(formattedDate, formatter);

時區

1. java.time.ZoneId類:替換java.util.TimeZone的新時區類。

2. 舉例

    a) 獲取時區

1 // 北京時間
2 ZoneId beijingZone = ZoneId.of("Asia/Shanghai");
3 // 默認時區
4 ZoneId zoneId = TimeZone.getDefault().toZoneId();

    b) 設置時區

1 LocalDate date = LocalDate.of(2014, Month.MARCH, 18);
2 ZonedDateTime zdt1 = date.atStartOfDay(beijingZone);
3 LocalDateTime dateTime = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45);
4 ZonedDateTime zdt2 = dateTime.atZone(beijingZone);
5 Instant instant = Instant.now();
6 ZonedDateTime zdt3 = instant.atZone(beijingZone);

 

做者:netoxi
出處:http://www.cnblogs.com/netoxi本文版權歸做者和博客園共有,歡迎轉載,未經贊成須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。歡迎指正與交流。

相關文章
相關標籤/搜索