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本文版权归做者和博客园共有,欢迎转载,未经赞成须保留此段声明,且在文章页面明显位置给出原文链接。欢迎指正与交流。

相关文章
相关标签/搜索