· 默認方法和靜態方法java
· 初步理解程序員
· 應用模式編程
· 優先級問題安全
· Optional網絡
· 基本用法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 }
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"));
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 }
1. 並行流與順序流+CompletableFuture均可以實現流的並行處理,如何選取?
a) 靈活
i. 並行流:線程數由ForkJoinPool的全局屬性決定。
ii. 順序流+CompletableFuture:自由建立線程池,靈活控制線程數。
b) 場景
i. 並行流:更適合計算密集型而且沒有I/O的操做,由於實現簡單,同時效率更高(若是全部的線程都是計算密集型,則沒有必要建立比CPU核數更多的線程)。
ii. 順序流+CompletableFuture:更適合並行工做單元涉及I/O等待(包括網絡鏈接等待)的操做,該場景不使用並行流的另外一個緣由是處理流的流水線中若是發生I/O等待,流的延遲特性會讓咱們很難判斷到底何時觸發了等待。該場景線程數用如下公式計算(出自《Java併發編程實戰》):
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 }
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本文版權歸做者和博客園共有,歡迎轉載,未經贊成須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。歡迎指正與交流。