1. 程式人生 > 實用技巧 >Java基礎進階:時間類要點摘要,時間Date類實現格式化與解析原始碼實現詳解,LocalDateTime時間類格式化與解析原始碼實現詳解,Period,Duration獲取時間間隔與原始碼實現,程式異常解析與處理方式

Java基礎進階:時間類要點摘要,時間Date類實現格式化與解析原始碼實現詳解,LocalDateTime時間類格式化與解析原始碼實現詳解,Period,Duration獲取時間間隔與原始碼實現,程式異常解析與處理方式

                      

                    要點摘要

                      課堂筆記

日期相關

JDK7

  • 日期類-Date

    • 概述

      • 表示一個時間點物件,這個時間點是以1970年1月1日為參考點;

    • 作用

      • 可以通過該類的物件,表示一個時間,並面向物件操作時間;

    • 構造方法

      • 直接利用空引數構造方法,即可獲取當前時間物件;

    • 常用方法

      • getTime()可以獲取時間物件對應的毫秒值

  • 格式化類-SimpleDateFormat

    • 概述

      • 專門用於將時間物件與字串進行相互轉換的工具類;

    • 作用

      • 1:可以將時間物件轉字串

      • 2:可以將字串轉成時間物件

    • 構造方法

      • 傳遞一個字串實參的構造方法

        年: yyyy

        月: MM

        日: dd

        時: HH

        分: mm

        秒: ss

        星期: E

    • 常用方法

      • parse(字串) 將字串轉成時間物件

      • format(Date物件) 將時間物件轉字串

JDK8

  • 日期類

    • 分類

      • LocalDateTime 包含年月日時分秒資訊的物件

      • LocalDate 包含年月日資訊的物件

      • LocalTime 包含時分秒資訊的物件

    • 獲取方式

      • 1:利用靜態方法 now() 獲取當前時間物件

      • 2:利用靜態方法of(資訊...) 獲取指定資訊物件

    • 常用方法

      • 1:getXxx() 以get開頭的方法都是獲取資訊,後面可以是年,月,日...

      • 2:plusXxx(資料量) 以plus開頭的方法都是增加時間量,可正可負

      • 3:withXxx(資訊) 以with開頭的方法都是修改物件的資訊

      • 4:format(DateTimeFormatter) 按照指定格式格式化該時間物件

      • 5:parse(字串,DateTimeFormatter) 按照指定格式解析字串中的資訊封裝到新的時間物件中

  • 格式化類-DateTimeFormatter

    • 作用

      • 配合JDK8的時間物件,完成格式化日期或解析字串

    • 獲取方式

      • 利用靜態方法 ofPattern​(String pattern)

    • 常用方法

      • parse(字串) 將字串轉成時間物件

      • format(JDK8時間物件) 將時間物件轉字串

  • 日期間隔物件(時間段)

    • 分類

      • 1:Period 計算年月日

      • 2:Duration 計算時分秒

    • 獲取方式

      • 靜態方法 between​(時間1,時間2)

    • 常用方法

      • getXxx() 直接獲取年月日時分秒資訊即可

異常相關

快速入門

  • 概述

    • 異常就是程式出現了不正常的情況

  • 分類

    • 編譯時期異常(Exception系列)

    • 執行時期異常(RuntimeException系列)

  • 體系

    • 其實RuntimeException是Exception的子類,但是RuntimeException太特殊了,所以另立門戶了;

  • JVM對異常的預設處理方式

    • 第1步:提示程式中出現異常的位置和原因;

    • 第2步:結束程式;

進階處理

  • 為什麼要處理異常

    • 當程式中出現編譯時期異常的時候,我們必須處理,不處理語法編譯報錯;

    • 當程式中出現執行時期異常的時候,我們可以處理也可以不處理,可以根據自己的實際需求靈活選擇,但是如果不處理,真的發生執行時異常時,JVM會按照預設處理方式處理髮生的異常,如果我們寫出了處理方案,那麼JVM就會按照我們給出的處理方案處理異常,處理後,程式不會停止,可以繼續執行;

  • 如何處理異常

    • 1:捕獲處理

      • 第1步

        • 使用try{}catch(){}對可能發生異常的程式碼進行包裹

      • 第2步

        • 在catch(){}大括號中給出解決辦法

      • 相關API

        • 一般會使用異常物件呼叫printStackTrace()方法,可以在控制檯展示異常資訊;(注意僅僅是展示異常資訊而已,展示後,程式並不會停止執行)

    • 2:宣告丟擲

      • 使用throws關鍵字把這個異常交給方法的呼叫者處理;(相當於把處理異常的權利交給呼叫方法的人了)

自定義異常類

  • 為什麼要自定義異常類

    • 因為java編寫好的異常類不足以描述我們程式中的問題了;

  • 如何自定義異常類

    • 自定義的類繼承java異常體系中的任意一個類即可,注意如果繼承的是Exception系列,那麼我們自定義的異常就屬於編譯時期異常,如果繼承的是RuntimeException,那麼我們自定義的異常就屬於執行時期異常;(簡單記: 喊爹即可)

  • 如何處理自定義異常類

    • 依然按照上面的異常處理方式處理;(參考進階處理)

注意事項

  • throws和throw的區別

    • 1:含義不同

      • throws表示宣告異常;重在"宣告"二字;

        相當於告訴呼叫方法的人,方法中有發生異常的可能,強調的是一種可能性,所以即使執行了throws的程式碼,也有可能不發生異常

      • throw表示丟擲異常;重在"丟擲"二字;

        也就是說一旦執行了這個程式碼,就一定會丟擲一個異常物件,強調的是丟擲異常的動作;

    • 2:使用位置不同

      • throws用在方法聲明後面,跟的是異常類名

      • throw用在方法體內,跟的是異常物件名

       

                        原始碼實現

1.時間日期類

1.1 Date類(應用)

  • 計算機中時間原點

    1970年1月1日 00:00:00

  • 時間換算單位

    1秒 = 1000毫秒

  • Date類概述

    Date 代表了一個特定的時間,精確到毫秒

  • Date類構造方法

    方法名說明
    public Date() 分配一個 Date物件,並初始化,以便它代表它被分配的時間,精確到毫秒
    public Date(long date) 分配一個 Date物件,並將其初始化為表示從標準基準時間起指定的毫秒數
  • 示例程式碼

    public class DateDemo01 {
    public static void main(String[] args) {
    //public Date():分配一個 Date物件,並初始化,以便它代表它被分配的時間,精確到毫秒
    Date d1 = new Date();
    System.out.println(d1);

    //public Date(long date):分配一個 Date物件,並將其初始化為表示從標準基準時間起指定的毫秒數
    long date = 1000*60*60;
    Date d2 = new Date(date);
    System.out.println(d2);
    }
    }

1.2 Date類常用方法(應用)

  • 常用方法

    方法名說明
    public long getTime() 獲取的是日期物件從1970年1月1日 00:00:00到現在的毫秒值
    public void setTime(long time) 設定時間,給的是毫秒值
  • 示例程式碼

    public class DateDemo02 {
    public static void main(String[] args) {
    //建立日期物件
    Date d = new Date();

    //public long getTime():獲取的是日期物件從1970年1月1日 00:00:00到現在的毫秒值
    // System.out.println(d.getTime());
    // System.out.println(d.getTime() * 1.0 / 1000 / 60 / 60 / 24 / 365 + "年");

    //public void setTime(long time):設定時間,給的是毫秒值
    // long time = 1000*60*60;
    long time = System.currentTimeMillis();
    d.setTime(time);

    System.out.println(d);
    }
    }

1.3 SimpleDateFormat類(應用)

  • SimpleDateFormat類概述

    SimpleDateFormat是一個具體的類,用於以區域設定敏感的方式格式化和解析日期。

    我們重點學習日期格式化和解析

  • SimpleDateFormat類構造方法

    方法名說明
    public SimpleDateFormat() 構造一個SimpleDateFormat,使用預設模式和日期格式
    public SimpleDateFormat(String pattern) 構造一個SimpleDateFormat使用給定的模式和預設的日期格式
  • SimpleDateFormat類的常用方法

    • 格式化(從Date到String)

      • public final String format(Date date):將日期格式化成日期/時間字串

    • 解析(從String到Date)

      • public Date parse(String source):從給定字串的開始解析文字以生成日期

  • 示例程式碼

    public class SimpleDateFormatDemo {
    public static void main(String[] args) throws ParseException {
    //格式化:從 Date 到 String
    Date d = new Date();
    // SimpleDateFormat sdf = new SimpleDateFormat();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
    String s = sdf.format(d);
    System.out.println(s);
    System.out.println("--------");

    //從 String 到 Date
    String ss = "2048-08-09 11:11:11";
    //ParseException
    SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date dd = sdf2.parse(ss);
    System.out.println(dd);
    }
    }

1.4 時間日期類練習 (應用)

  • 需求

    秒殺開始時間是2020年11月11日 00:00:00,結束時間是2020年11月11日 00:10:00,使用者小賈下單時間是2020年11月11日 00:03:47,使用者小皮下單時間是2020年11月11日 00:10:11,判斷使用者有沒有成功參與秒殺活動

  • 實現步驟

    1. 判斷下單時間是否在開始到結束的範圍內

    2. 把字串形式的時間變成毫秒值

  • 程式碼實現

    public class DateDemo5 {
    public static void main(String[] args) throws ParseException {
    //開始時間:2020年11月11日 0:0:0
    //結束時間:2020年11月11日 0:10:0

    //小賈2020年11月11日 0:03:47
    //小皮2020年11月11日 0:10:11

    //1.判斷兩位同學的下單時間是否在範圍之內就可以了。

    //2.要把每一個時間都換算成毫秒值。

    String start = "2020年11月11日 0:0:0";
    String end = "2020年11月11日 0:10:0";

    String jia = "2020年11月11日 0:03:47";
    String pi = "2020年11月11日 0:10:11";

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
    long startTime = sdf.parse(start).getTime();
    long endTime = sdf.parse(end).getTime();

    // System.out.println(startTime);
    // System.out.println(endTime);
    long jiaTime = sdf.parse(jia).getTime();
    long piTime = sdf.parse(pi).getTime();

    if(jiaTime >= startTime && jiaTime <= endTime){
    System.out.println("小賈同學參加上了秒殺活動");
    }else{
    System.out.println("小賈同學沒有參加上秒殺活動");
    }

    System.out.println("------------------------");

    if(piTime >= startTime && piTime <= endTime){
    System.out.println("小皮同學參加上了秒殺活動");
    }else{
    System.out.println("小皮同學沒有參加上秒殺活動");
    }

    }

    }

2.JDK8時間日期類

2.1 JDK8新增日期類 (理解)

  • LocalDate 表示日期(年月日)

  • LocalTime 表示時間(時分秒)

  • LocalDateTime 表示時間+ 日期 (年月日時分秒)

2.2 LocalDateTime建立方法 (應用)

  • 方法說明

    方法名說明
    public static LocalDateTime now() 獲取當前系統時間
    public static LocalDateTime of (年, 月 , 日, 時, 分, 秒) 使用指定年月日和時分秒初始化一個LocalDateTime物件
  • 示例程式碼

    public class JDK8DateDemo2 {
    public static void main(String[] args) {
    LocalDateTime now = LocalDateTime.now();
    System.out.println(now);

    LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 11, 11, 11);
    System.out.println(localDateTime);
    }
    }

2.3 LocalDateTime獲取方法 (應用)

  • 方法說明

    方法名說明
    public int getYear() 獲取年
    public int getMonthValue() 獲取月份(1-12)
    public int getDayOfMonth() 獲取月份中的第幾天(1-31)
    public int getDayOfYear() 獲取一年中的第幾天(1-366)
    public DayOfWeek getDayOfWeek() 獲取星期
    public int getMinute() 獲取分鐘
    public int getHour() 獲取小時
  • 示例程式碼

    public class JDK8DateDemo3 {
    public static void main(String[] args) {
    LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 11, 11, 20);
    //public int getYear() 獲取年
    int year = localDateTime.getYear();
    System.out.println("年為" +year);
    //public int getMonthValue() 獲取月份(1-12)
    int month = localDateTime.getMonthValue();
    System.out.println("月份為" + month);

    Month month1 = localDateTime.getMonth();
    // System.out.println(month1);

    //public int getDayOfMonth() 獲取月份中的第幾天(1-31)
    int day = localDateTime.getDayOfMonth();
    System.out.println("日期為" + day);

    //public int getDayOfYear() 獲取一年中的第幾天(1-366)
    int dayOfYear = localDateTime.getDayOfYear();
    System.out.println("這是一年中的第" + dayOfYear + "天");

    //public DayOfWeek getDayOfWeek()獲取星期
    DayOfWeek dayOfWeek = localDateTime.getDayOfWeek();
    System.out.println("星期為" + dayOfWeek);

    //public int getMinute() 獲取分鐘
    int minute = localDateTime.getMinute();
    System.out.println("分鐘為" + minute);
    //public int getHour() 獲取小時

    int hour = localDateTime.getHour();
    System.out.println("小時為" + hour);
    }
    }

2.4 LocalDateTime轉換方法 (應用)

  • 方法說明

    方法名說明
    public LocalDate toLocalDate () 轉換成為一個LocalDate物件
    public LocalTime toLocalTime () 轉換成為一個LocalTime物件
  • 示例程式碼

    public class JDK8DateDemo4 {
    public static void main(String[] args) {
    LocalDateTime localDateTime = LocalDateTime.of(2020, 12, 12, 8, 10, 12);
    //public LocalDate toLocalDate () 轉換成為一個LocalDate物件
    LocalDate localDate = localDateTime.toLocalDate();
    System.out.println(localDate);

    //public LocalTime toLocalTime () 轉換成為一個LocalTime物件
    LocalTime localTime = localDateTime.toLocalTime();
    System.out.println(localTime);
    }
    }

2.5 LocalDateTime格式化和解析 (應用)

  • 方法說明

    方法名說明
    public String format (指定格式) 把一個LocalDateTime格式化成為一個字串
    public LocalDateTime parse (準備解析的字串, 解析格式) 把一個日期字串解析成為一個LocalDateTime物件
    public static DateTimeFormatter ofPattern(String pattern) 使用指定的日期模板獲取一個日期格式化器DateTimeFormatter物件
  • 示例程式碼

    public class JDK8DateDemo5 {
    public static void main(String[] args) {
    //method1();
    //method2();
    }

    private static void method2() {
    //public static LocalDateTime parse (準備解析的字串, 解析格式) 把一個日期字串解析成為一個LocalDateTime物件
    String s = "2020年11月12日 13:14:15";
    DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
    LocalDateTime parse = LocalDateTime.parse(s, pattern);
    System.out.println(parse);
    }

    private static void method1() {
    LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 12, 13, 14, 15);
    System.out.println(localDateTime);
    //public String format (指定格式) 把一個LocalDateTime格式化成為一個字串
    DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
    String s = localDateTime.format(pattern);
    System.out.println(s);
    }
    }

2.6 LocalDateTime增加或者減少時間的方法 (應用)

  • 方法說明

    方法名說明
    public LocalDateTime plusYears (long years) 新增或者減去年
    public LocalDateTime plusMonths(long months) 新增或者減去月
    public LocalDateTime plusDays(long days) 新增或者減去日
    public LocalDateTime plusHours(long hours) 新增或者減去時
    public LocalDateTime plusMinutes(long minutes) 新增或者減去分
    public LocalDateTime plusSeconds(long seconds) 新增或者減去秒
    public LocalDateTime plusWeeks(long weeks) 新增或者減去周
  • 示例程式碼

    /**
    * JDK8 時間類新增或者減去時間的方法
    */
    public class JDK8DateDemo6 {
    public static void main(String[] args) {
    //public LocalDateTime plusYears (long years) 新增或者減去年

    LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 13, 14, 15);
    //LocalDateTime newLocalDateTime = localDateTime.plusYears(1);
    //System.out.println(newLocalDateTime);

    LocalDateTime newLocalDateTime = localDateTime.plusYears(-1);
    System.out.println(newLocalDateTime);
    }
    }

2.7 LocalDateTime減少或者增加時間的方法 (應用)

  • 方法說明

    方法名說明
    public LocalDateTime minusYears (long years) 減去或者新增年
    public LocalDateTime minusMonths(long months) 減去或者新增月
    public LocalDateTime minusDays(long days) 減去或者新增日
    public LocalDateTime minusHours(long hours) 減去或者新增時
    public LocalDateTime minusMinutes(long minutes) 減去或者新增分
    public LocalDateTime minusSeconds(long seconds) 減去或者新增秒
    public LocalDateTime minusWeeks(long weeks) 減去或者新增周
  • 示例程式碼

    /**
    * JDK8 時間類減少或者新增時間的方法
    */
    public class JDK8DateDemo7 {
    public static void main(String[] args) {
    //public LocalDateTime minusYears (long years) 減去或者新增年
    LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 13, 14, 15);
    //LocalDateTime newLocalDateTime = localDateTime.minusYears(1);
    //System.out.println(newLocalDateTime);

    LocalDateTime newLocalDateTime = localDateTime.minusYears(-1);
    System.out.println(newLocalDateTime);

    }
    }

2.8 LocalDateTime修改方法 (應用)

  • 方法說明

    方法名說明
    public LocalDateTime withYear(int year) 直接修改年
    public LocalDateTime withMonth(int month) 直接修改月
    public LocalDateTime withDayOfMonth(int dayofmonth) 直接修改日期(一個月中的第幾天)
    public LocalDateTime withDayOfYear(int dayOfYear) 直接修改日期(一年中的第幾天)
    public LocalDateTime withHour(int hour) 直接修改小時
    public LocalDateTime withMinute(int minute) 直接修改分鐘
    public LocalDateTime withSecond(int second) 直接修改秒
  • 示例程式碼

    /**
    * JDK8 時間類修改時間
    */
    public class JDK8DateDemo8 {
    public static void main(String[] args) {
    //public LocalDateTime withYear(int year) 修改年
    LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 13, 14, 15);
    // LocalDateTime newLocalDateTime = localDateTime.withYear(2048);
    // System.out.println(newLocalDateTime);

    LocalDateTime newLocalDateTime = localDateTime.withMonth(20);
    System.out.println(newLocalDateTime);

    }
    }

2.9 Period (應用)

  • 方法說明

    方法名說明
    public static Period between(開始時間,結束時間) 計算兩個“時間"的間隔
    public int getYears() 獲得這段時間的年數
    public int getMonths() 獲得此期間的總月數
    public int getDays() 獲得此期間的天數
    public long toTotalMonths() 獲取此期間的總月數
  • 示例程式碼

    /**
    * 計算兩個時間的間隔
    */
    public class JDK8DateDemo9 {
    public static void main(String[] args) {
    //public static Period between(開始時間,結束時間) 計算兩個"時間"的間隔

    LocalDate localDate1 = LocalDate.of(2020, 1, 1);
    LocalDate localDate2 = LocalDate.of(2048, 12, 12);
    Period period = Period.between(localDate1, localDate2);
    System.out.println(period);//P28Y11M11D

    //public int getYears() 獲得這段時間的年數
    System.out.println(period.getYears());//28
    //public int getMonths() 獲得此期間的月數
    System.out.println(period.getMonths());//11
    //public int getDays() 獲得此期間的天數
    System.out.println(period.getDays());//11

    //public long toTotalMonths() 獲取此期間的總月數
    System.out.println(period.toTotalMonths());//347

    }
    }

2.10 Duration (應用)

  • 方法說明

    方法名說明
    public static Durationbetween(開始時間,結束時間) 計算兩個“時間"的間隔
    public long toSeconds() 獲得此時間間隔的秒
    public int toMillis() 獲得此時間間隔的毫秒
    public int toNanos() 獲得此時間間隔的納秒
  • 示例程式碼

    /**
    * 計算兩個時間的間隔
    */
    public class JDK8DateDemo10 {
    public static void main(String[] args) {
    //public static Duration between(開始時間,結束時間) 計算兩個“時間"的間隔

    LocalDateTime localDateTime1 = LocalDateTime.of(2020, 1, 1, 13, 14, 15);
    LocalDateTime localDateTime2 = LocalDateTime.of(2020, 1, 2, 11, 12, 13);
    Duration duration = Duration.between(localDateTime1, localDateTime2);
    System.out.println(duration);//PT21H57M58S
    //public long toSeconds() 獲得此時間間隔的秒
    System.out.println(duration.toSeconds());//79078
    //public int toMillis() 獲得此時間間隔的毫秒
    System.out.println(duration.toMillis());//79078000
    //public int toNanos() 獲得此時間間隔的納秒
    System.out.println(duration.toNanos());//79078000000000
    }
    }

3.異常

3.1 異常(記憶)

  • 異常的概述

    異常就是程式出現了不正常的情況

  • 異常的體系結構

      

3.2 編譯時異常和執行時異常的區別(記憶)

  • 編譯時異常

    • 都是Exception類及其子類

    • 必須顯示處理,否則程式就會發生錯誤,無法通過編譯

  • 執行時異常

    • 都是RuntimeException類及其子類

    • 無需顯示處理,也可以和編譯時異常一樣處理

  • 圖示

    

3.3 JVM預設處理異常的方式(理解)

  • 如果程式出現了問題,我們沒有做任何處理,最終JVM 會做預設的處理,處理方式有如下兩個步驟:

    • 把異常的名稱,錯誤原因及異常出現的位置等資訊輸出在了控制檯

    • 程式停止執行

3.4 檢視異常資訊 (理解)

控制檯在列印異常資訊時,會列印異常類名,異常出現的原因,異常出現的位置

我們調bug時,可以根據提示,找到異常出現的位置,分析原因,修改異常程式碼

3.5 throws方式處理異常(應用)

  • 定義格式

    public void 方法() throws 異常類名 {

    }
  • 示例程式碼

    public class ExceptionDemo {
    public static void main(String[] args) throws ParseException{
    System.out.println("開始");
    // method();
    method2();

    System.out.println("結束");
    }

    //編譯時異常
    public static void method2() throws ParseException {
    String s = "2048-08-09";
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    Date d = sdf.parse(s);
    System.out.println(d);
    }

    //執行時異常
    public static void method() throws ArrayIndexOutOfBoundsException {
    int[] arr = {1, 2, 3};
    System.out.println(arr[3]);
    }
    }
  • 注意事項

    • 這個throws格式是跟在方法的括號後面的

    • 編譯時異常必須要進行處理,兩種處理方案:try...catch …或者 throws,如果採用 throws 這種方案,在方法上進行顯示宣告,將來誰呼叫這個方法誰處理

    • 執行時異常因為在執行時才會發生,所以在方法後面可以不寫,執行時出現異常預設交給jvm處理

3.6 throw丟擲異常 (應用)

  • 格式

    throw new 異常();

  • 注意

    這個格式是在方法內的,表示當前程式碼手動丟擲一個異常,下面的程式碼不用再執行了

  • throws和throw的區別

    THROWSTHROW
    用在方法聲明後面,跟的是異常類名 用在方法體內,跟的是異常物件名
    表示宣告異常,呼叫該方法有可能會出現這樣的異常 表示手動丟擲異常物件,由方法體內的語句處理
  • 示例程式碼

    public class ExceptionDemo8 {
    public static void main(String[] args) {
    //int [] arr = {1,2,3,4,5};
    int [] arr = null;
    printArr(arr);//就會 接收到一個異常.
    //我們還需要自己處理一下異常.
    }

    private static void printArr(int[] arr) {
    if(arr == null){
    //呼叫者知道成功列印了嗎?
    //System.out.println("引數不能為null");
    throw new NullPointerException(); //當引數為null的時候
    //手動建立了一個異常物件,拋給了呼叫者,產生了一個異常
    }else{
    for (int i = 0; i < arr.length; i++) {
    System.out.println(arr[i]);
    }
    }
    }

    }

3.7 try-catch方式處理異常(應用)

  • 定義格式

    try {
    	可能出現異常的程式碼;
    } catch(異常類名 變數名) {
    	異常的處理程式碼;
    }
  • 執行流程

    • 程式從 try 裡面的程式碼開始執行

    • 出現異常,就會跳轉到對應的 catch 裡面去執行

    • 執行完畢之後,程式還可以繼續往下執行

  • 示例程式碼

    public class ExceptionDemo01 {
        public static void main(String[] args) {
            System.out.println("開始");
            method();
            System.out.println("結束");
        }
    
        public static void method() {
            try {
                int[] arr = {1, 2, 3};
                System.out.println(arr[3]);
                System.out.println("這裡能夠訪問到嗎");
            } catch (ArrayIndexOutOfBoundsException e) {
                System.out.println("你訪問的陣列索引不存在,請回去修改為正確的索引");
            }
        }
    }
  • 注意

    1. 如果 try 中沒有遇到問題,怎麼執行?

      會把try中所有的程式碼全部執行完畢,不會執行catch裡面的程式碼

    2. 如果 try 中遇到了問題,那麼 try 下面的程式碼還會執行嗎?

      那麼直接跳轉到對應的catch語句中,try下面的程式碼就不會再執行了當catch裡面的語句全部執行完畢,表示整個體系全部執行完全,繼續執行下面的程式碼

    3. 如果出現的問題沒有被捕獲,那麼程式如何執行?

      那麼try...catch就相當於沒有寫.那麼也就是自己沒有處理.預設交給虛擬機器處理.

    4. 同時有可能出現多個異常怎麼處理?

      出現多個異常,那麼就寫多個catch就可以了.注意點:如果多個異常之間存在子父類關係.那麼父類一定要寫在下面

3.8 Throwable成員方法(應用)

  • 常用方法

    方法名說明
    public String getMessage() 返回此 throwable 的詳細訊息字串
    public String toString() 返回此可丟擲的簡短描述
    public void printStackTrace() 把異常的錯誤資訊輸出在控制檯
  • 示例程式碼

    public class ExceptionDemo02 {
        public static void main(String[] args) {
            System.out.println("開始");
            method();
            System.out.println("結束");
        }
    
        public static void method() {
            try {
                int[] arr = {1, 2, 3};
                System.out.println(arr[3]); //new ArrayIndexOutOfBoundsException();
                System.out.println("這裡能夠訪問到嗎");
            } catch (ArrayIndexOutOfBoundsException e) { //new ArrayIndexOutOfBoundsException();
    //            e.printStackTrace();
    
                //public String getMessage():返回此 throwable 的詳細訊息字串
    //            System.out.println(e.getMessage());
                //Index 3 out of bounds for length 3
    
                //public String toString():返回此可丟擲的簡短描述
    //            System.out.println(e.toString());
                //java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
    
                //public void printStackTrace():把異常的錯誤資訊輸出在控制檯
                e.printStackTrace();
    //            java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
    //            at com.itheima_02.ExceptionDemo02.method(ExceptionDemo02.java:18)
    //            at com.itheima_02.ExceptionDemo02.main(ExceptionDemo02.java:11)
    
            }
        }
    }

3.9 異常的練習 (應用)

  • 需求

    鍵盤錄入學生的姓名和年齡,其中年齡為18 - 25歲,超出這個範圍是異常資料不能賦值.需要重新錄入,一直錄到正確為止

  • 實現步驟

    1. 建立學生物件

    2. 鍵盤錄入姓名和年齡,並賦值給學生物件

    3. 如果是非法資料就再次錄入

  • 程式碼實現

    學生類

    public class Student {
        private String name;
        private int age;
    
        public Student() {
        }
    
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            if(age >= 18 && age <= 25){
                this.age = age;
            }else{
                //當年齡不合法時,產生一個異常
                throw new RuntimeException("年齡超出了範圍");
            }
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

    測試類

    public class ExceptionDemo12 {
        public static void main(String[] args) {
            // 鍵盤錄入學生的姓名和年齡,其中年齡為 18 - 25歲,
            // 超出這個範圍是異常資料不能賦值.需要重新錄入,一直錄到正確為止。
    
            Student s = new Student();
    
            Scanner sc = new Scanner(System.in);
            System.out.println("請輸入姓名");
            String name = sc.nextLine();
            s.setName(name);
           while(true){
               System.out.println("請輸入年齡");
               String ageStr = sc.nextLine();
               try {
                   int age = Integer.parseInt(ageStr);
                   s.setAge(age);
                   break;
               } catch (NumberFormatException e) {
                   System.out.println("請輸入一個整數");
                   continue;
               } catch (AgeOutOfBoundsException e) {
                   System.out.println(e.toString());
                   System.out.println("請輸入一個符合範圍的年齡");
                   continue;
               }
               /*if(age >= 18 && age <=25){
                   s.setAge(age);
                   break;
               }else{
                   System.out.println("請輸入符合要求的年齡");
                   continue;
               }*/
           }
            System.out.println(s);
    
        }
    }

3.10 自定義異常(應用)

  • 自定義異常概述

    當Java中提供的異常不能滿足我們的需求時,我們可以自定義異常

  • 實現步驟

    1. 定義異常類

    2. 寫繼承關係

    3. 提供空參構造

    4. 提供帶參構造

  • 程式碼實現

    異常類

    public class AgeOutOfBoundsException extends RuntimeException {
        public AgeOutOfBoundsException() {
        }
    
        public AgeOutOfBoundsException(String message) {
            super(message);
        }
    }

    學生類

    public class Student {
        private String name;
        private int age;
    
        public Student() {
        }
    
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            if(age >= 18 && age <= 25){
                this.age = age;
            }else{
                //如果Java中提供的異常不能滿足我們的需求,我們可以使用自定義的異常
                throw new AgeOutOfBoundsException("年齡超出了範圍");
            }
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

    測試類

    public class ExceptionDemo12 {
        public static void main(String[] args) {
            // 鍵盤錄入學生的姓名和年齡,其中年齡為 18 - 25歲,
            // 超出這個範圍是異常資料不能賦值.需要重新錄入,一直錄到正確為止。
    
            Student s = new Student();
    
            Scanner sc = new Scanner(System.in);
            System.out.println("請輸入姓名");
            String name = sc.nextLine();
            s.setName(name);
           while(true){
               System.out.println("請輸入年齡");
               String ageStr = sc.nextLine();
               try {
                   int age = Integer.parseInt(ageStr);
                   s.setAge(age);
                   break;
               } catch (NumberFormatException e) {
                   System.out.println("請輸入一個整數");
                   continue;
               } catch (AgeOutOfBoundsException e) {
                   System.out.println(e.toString());
                   System.out.println("請輸入一個符合範圍的年齡");
                   continue;
               }
               /*if(age >= 18 && age <=25){
                   s.setAge(age);
                   break;
               }else{
                   System.out.println("請輸入符合要求的年齡");
                   continue;
               }*/
           }
            System.out.println(s);
    
        }
    }

1.時間日期類

1.1 Date類(應用)

  • 計算機中時間原點

    1970年1月1日 00:00:00

  • 時間換算單位

    1秒 = 1000毫秒

  • Date類概述

    Date 代表了一個特定的時間,精確到毫秒

  • Date類構造方法

    方法名說明
    public Date() 分配一個 Date物件,並初始化,以便它代表它被分配的時間,精確到毫秒
    public Date(long date) 分配一個 Date物件,並將其初始化為表示從標準基準時間起指定的毫秒數
  • 示例程式碼

    public class DateDemo01 {
    public static void main(String[] args) {
    //public Date():分配一個 Date物件,並初始化,以便它代表它被分配的時間,精確到毫秒
    Date d1 = new Date();
    System.out.println(d1);

    //public Date(long date):分配一個 Date物件,並將其初始化為表示從標準基準時間起指定的毫秒數
    long date = 1000*60*60;
    Date d2 = new Date(date);
    System.out.println(d2);
    }
    }

1.2 Date類常用方法(應用)

  • 常用方法

    方法名說明
    public long getTime() 獲取的是日期物件從1970年1月1日 00:00:00到現在的毫秒值
    public void setTime(long time) 設定時間,給的是毫秒值
  • 示例程式碼

    public class DateDemo02 {
    public static void main(String[] args) {
    //建立日期物件
    Date d = new Date();

    //public long getTime():獲取的是日期物件從1970年1月1日 00:00:00到現在的毫秒值
    // System.out.println(d.getTime());
    // System.out.println(d.getTime() * 1.0 / 1000 / 60 / 60 / 24 / 365 + "年");

    //public void setTime(long time):設定時間,給的是毫秒值
    // long time = 1000*60*60;
    long time = System.currentTimeMillis();
    d.setTime(time);

    System.out.println(d);
    }
    }

1.3 SimpleDateFormat類(應用)

  • SimpleDateFormat類概述

    SimpleDateFormat是一個具體的類,用於以區域設定敏感的方式格式化和解析日期。

    我們重點學習日期格式化和解析

  • SimpleDateFormat類構造方法

    方法名說明
    public SimpleDateFormat() 構造一個SimpleDateFormat,使用預設模式和日期格式
    public SimpleDateFormat(String pattern) 構造一個SimpleDateFormat使用給定的模式和預設的日期格式
  • SimpleDateFormat類的常用方法

    • 格式化(從Date到String)

      • public final String format(Date date):將日期格式化成日期/時間字串

    • 解析(從String到Date)

      • public Date parse(String source):從給定字串的開始解析文字以生成日期

  • 示例程式碼

    public class SimpleDateFormatDemo {
    public static void main(String[] args) throws ParseException {
    //格式化:從 Date 到 String
    Date d = new Date();
    // SimpleDateFormat sdf = new SimpleDateFormat();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
    String s = sdf.format(d);
    System.out.println(s);
    System.out.println("--------");

    //從 String 到 Date
    String ss = "2048-08-09 11:11:11";
    //ParseException
    SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date dd = sdf2.parse(ss);
    System.out.println(dd);
    }
    }

1.4 時間日期類練習 (應用)

  • 需求

    秒殺開始時間是2020年11月11日 00:00:00,結束時間是2020年11月11日 00:10:00,使用者小賈下單時間是2020年11月11日 00:03:47,使用者小皮下單時間是2020年11月11日 00:10:11,判斷使用者有沒有成功參與秒殺活動

  • 實現步驟

    1. 判斷下單時間是否在開始到結束的範圍內

    2. 把字串形式的時間變成毫秒值

  • 程式碼實現

    public class DateDemo5 {
    public static void main(String[] args) throws ParseException {
    //開始時間:2020年11月11日 0:0:0
    //結束時間:2020年11月11日 0:10:0

    //小賈2020年11月11日 0:03:47
    //小皮2020年11月11日 0:10:11

    //1.判斷兩位同學的下單時間是否在範圍之內就可以了。

    //2.要把每一個時間都換算成毫秒值。

    String start = "2020年11月11日 0:0:0";
    String end = "2020年11月11日 0:10:0";

    String jia = "2020年11月11日 0:03:47";
    String pi = "2020年11月11日 0:10:11";

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
    long startTime = sdf.parse(start).getTime();
    long endTime = sdf.parse(end).getTime();

    // System.out.println(startTime);
    // System.out.println(endTime);
    long jiaTime = sdf.parse(jia).getTime();
    long piTime = sdf.parse(pi).getTime();

    if(jiaTime >= startTime && jiaTime <= endTime){
    System.out.println("小賈同學參加上了秒殺活動");
    }else{
    System.out.println("小賈同學沒有參加上秒殺活動");
    }

    System.out.println("------------------------");

    if(piTime >= startTime && piTime <= endTime){
    System.out.println("小皮同學參加上了秒殺活動");
    }else{
    System.out.println("小皮同學沒有參加上秒殺活動");
    }

    }

    }

2.JDK8時間日期類

2.1 JDK8新增日期類 (理解)

  • LocalDate 表示日期(年月日)

  • LocalTime 表示時間(時分秒)

  • LocalDateTime 表示時間+ 日期 (年月日時分秒)

2.2 LocalDateTime建立方法 (應用)

  • 方法說明

    方法名說明
    public static LocalDateTime now() 獲取當前系統時間
    public static LocalDateTime of (年, 月 , 日, 時, 分, 秒) 使用指定年月日和時分秒初始化一個LocalDateTime物件
  • 示例程式碼

    public class JDK8DateDemo2 {
    public static void main(String[] args) {
    LocalDateTime now = LocalDateTime.now();
    System.out.println(now);

    LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 11, 11, 11);
    System.out.println(localDateTime);
    }
    }

2.3 LocalDateTime獲取方法 (應用)

  • 方法說明

    方法名說明
    public int getYear() 獲取年
    public int getMonthValue() 獲取月份(1-12)
    public int getDayOfMonth() 獲取月份中的第幾天(1-31)
    public int getDayOfYear() 獲取一年中的第幾天(1-366)
    public DayOfWeek getDayOfWeek() 獲取星期
    public int getMinute() 獲取分鐘
    public int getHour() 獲取小時
  • 示例程式碼

    public class JDK8DateDemo3 {
    public static void main(String[] args) {
    LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 11, 11, 20);
    //public int getYear() 獲取年
    int year = localDateTime.getYear();
    System.out.println("年為" +year);
    //public int getMonthValue() 獲取月份(1-12)
    int month = localDateTime.getMonthValue();
    System.out.println("月份為" + month);

    Month month1 = localDateTime.getMonth();
    // System.out.println(month1);

    //public int getDayOfMonth() 獲取月份中的第幾天(1-31)
    int day = localDateTime.getDayOfMonth();
    System.out.println("日期為" + day);

    //public int getDayOfYear() 獲取一年中的第幾天(1-366)
    int dayOfYear = localDateTime.getDayOfYear();
    System.out.println("這是一年中的第" + dayOfYear + "天");

    //public DayOfWeek getDayOfWeek()獲取星期
    DayOfWeek dayOfWeek = localDateTime.getDayOfWeek();
    System.out.println("星期為" + dayOfWeek);

    //public int getMinute() 獲取分鐘
    int minute = localDateTime.getMinute();
    System.out.println("分鐘為" + minute);
    //public int getHour() 獲取小時

    int hour = localDateTime.getHour();
    System.out.println("小時為" + hour);
    }
    }

2.4 LocalDateTime轉換方法 (應用)

  • 方法說明

    方法名說明
    public LocalDate toLocalDate () 轉換成為一個LocalDate物件
    public LocalTime toLocalTime () 轉換成為一個LocalTime物件
  • 示例程式碼

    public class JDK8DateDemo4 {
    public static void main(String[] args) {
    LocalDateTime localDateTime = LocalDateTime.of(2020, 12, 12, 8, 10, 12);
    //public LocalDate toLocalDate () 轉換成為一個LocalDate物件
    LocalDate localDate = localDateTime.toLocalDate();
    System.out.println(localDate);

    //public LocalTime toLocalTime () 轉換成為一個LocalTime物件
    LocalTime localTime = localDateTime.toLocalTime();
    System.out.println(localTime);
    }
    }

2.5 LocalDateTime格式化和解析 (應用)

  • 方法說明

    方法名說明
    public String format (指定格式) 把一個LocalDateTime格式化成為一個字串
    public LocalDateTime parse (準備解析的字串, 解析格式) 把一個日期字串解析成為一個LocalDateTime物件
    public static DateTimeFormatter ofPattern(String pattern) 使用指定的日期模板獲取一個日期格式化器DateTimeFormatter物件
  • 示例程式碼

    public class JDK8DateDemo5 {
    public static void main(String[] args) {
    //method1();
    //method2();
    }

    private static void method2() {
    //public static LocalDateTime parse (準備解析的字串, 解析格式) 把一個日期字串解析成為一個LocalDateTime物件
    String s = "2020年11月12日 13:14:15";
    DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
    LocalDateTime parse = LocalDateTime.parse(s, pattern);
    System.out.println(parse);
    }

    private static void method1() {
    LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 12, 13, 14, 15);
    System.out.println(localDateTime);
    //public String format (指定格式) 把一個LocalDateTime格式化成為一個字串
    DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
    String s = localDateTime.format(pattern);
    System.out.println(s);
    }
    }

2.6 LocalDateTime增加或者減少時間的方法 (應用)

  • 方法說明

    方法名說明
    public LocalDateTime plusYears (long years) 新增或者減去年
    public LocalDateTime plusMonths(long months) 新增或者減去月
    public LocalDateTime plusDays(long days) 新增或者減去日
    public LocalDateTime plusHours(long hours) 新增或者減去時
    public LocalDateTime plusMinutes(long minutes) 新增或者減去分
    public LocalDateTime plusSeconds(long seconds) 新增或者減去秒
    public LocalDateTime plusWeeks(long weeks) 新增或者減去周
  • 示例程式碼

    /**
    * JDK8 時間類新增或者減去時間的方法
    */
    public class JDK8DateDemo6 {
    public static void main(String[] args) {
    //public LocalDateTime plusYears (long years) 新增或者減去年

    LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 13, 14, 15);
    //LocalDateTime newLocalDateTime = localDateTime.plusYears(1);
    //System.out.println(newLocalDateTime);

    LocalDateTime newLocalDateTime = localDateTime.plusYears(-1);
    System.out.println(newLocalDateTime);
    }
    }

2.7 LocalDateTime減少或者增加時間的方法 (應用)

  • 方法說明

    方法名說明
    public LocalDateTime minusYears (long years) 減去或者新增年
    public LocalDateTime minusMonths(long months) 減去或者新增月
    public LocalDateTime minusDays(long days) 減去或者新增日
    public LocalDateTime minusHours(long hours) 減去或者新增時
    public LocalDateTime minusMinutes(long minutes) 減去或者新增分
    public LocalDateTime minusSeconds(long seconds) 減去或者新增秒
    public LocalDateTime minusWeeks(long weeks) 減去或者新增周
  • 示例程式碼

    /**
    * JDK8 時間類減少或者新增時間的方法
    */
    public class JDK8DateDemo7 {
    public static void main(String[] args) {
    //public LocalDateTime minusYears (long years) 減去或者新增年
    LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 13, 14, 15);
    //LocalDateTime newLocalDateTime = localDateTime.minusYears(1);
    //System.out.println(newLocalDateTime);

    LocalDateTime newLocalDateTime = localDateTime.minusYears(-1);
    System.out.println(newLocalDateTime);

    }
    }

2.8 LocalDateTime修改方法 (應用)

  • 方法說明

    方法名說明
    public LocalDateTime withYear(int year) 直接修改年
    public LocalDateTime withMonth(int month) 直接修改月
    public LocalDateTime withDayOfMonth(int dayofmonth) 直接修改日期(一個月中的第幾天)
    public LocalDateTime withDayOfYear(int dayOfYear) 直接修改日期(一年中的第幾天)
    public LocalDateTime withHour(int hour) 直接修改小時
    public LocalDateTime withMinute(int minute) 直接修改分鐘
    public LocalDateTime withSecond(int second) 直接修改秒
  • 示例程式碼

    /**
    * JDK8 時間類修改時間
    */
    public class JDK8DateDemo8 {
    public static void main(String[] args) {
    //public LocalDateTime withYear(int year) 修改年
    LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 11, 13, 14, 15);
    // LocalDateTime newLocalDateTime = localDateTime.withYear(2048);
    // System.out.println(newLocalDateTime);

    LocalDateTime newLocalDateTime = localDateTime.withMonth(20);
    System.out.println(newLocalDateTime);

    }
    }

2.9 Period (應用)

  • 方法說明

    方法名說明
    public static Period between(開始時間,結束時間) 計算兩個“時間"的間隔
    public int getYears() 獲得這段時間的年數
    public int getMonths() 獲得此期間的總月數
    public int getDays() 獲得此期間的天數
    public long toTotalMonths() 獲取此期間的總月數
  • 示例程式碼

    /**
    * 計算兩個時間的間隔
    */
    public class JDK8DateDemo9 {
    public static void main(String[] args) {
    //public static Period between(開始時間,結束時間) 計算兩個"時間"的間隔

    LocalDate localDate1 = LocalDate.of(2020, 1, 1);
    LocalDate localDate2 = LocalDate.of(2048, 12, 12);
    Period period = Period.between(localDate1, localDate2);
    System.out.println(period);//P28Y11M11D

    //public int getYears() 獲得這段時間的年數
    System.out.println(period.getYears());//28
    //public int getMonths() 獲得此期間的月數
    System.out.println(period.getMonths());//11
    //public int getDays() 獲得此期間的天數
    System.out.println(period.getDays());//11

    //public long toTotalMonths() 獲取此期間的總月數
    System.out.println(period.toTotalMonths());//347

    }
    }

2.10 Duration (應用)

  • 方法說明

    方法名說明
    public static Durationbetween(開始時間,結束時間) 計算兩個“時間"的間隔
    public long toSeconds() 獲得此時間間隔的秒
    public int toMillis() 獲得此時間間隔的毫秒
    public int toNanos() 獲得此時間間隔的納秒
  • 示例程式碼

    /**
    * 計算兩個時間的間隔
    */
    public class JDK8DateDemo10 {
    public static void main(String[] args) {
    //public static Duration between(開始時間,結束時間) 計算兩個“時間"的間隔

    LocalDateTime localDateTime1 = LocalDateTime.of(2020, 1, 1, 13, 14, 15);
    LocalDateTime localDateTime2 = LocalDateTime.of(2020, 1, 2, 11, 12, 13);
    Duration duration = Duration.between(localDateTime1, localDateTime2);
    System.out.println(duration);//PT21H57M58S
    //public long toSeconds() 獲得此時間間隔的秒
    System.out.println(duration.toSeconds());//79078
    //public int toMillis() 獲得此時間間隔的毫秒
    System.out.println(duration.toMillis());//79078000
    //public int toNanos() 獲得此時間間隔的納秒
    System.out.println(duration.toNanos());//79078000000000
    }
    }

3.異常

3.1 異常(記憶)

  • 異常的概述

    異常就是程式出現了不正常的情況

  • 異常的體系結構

3.2 編譯時異常和執行時異常的區別(記憶)

  • 編譯時異常

    • 都是Exception類及其子類

    • 必須顯示處理,否則程式就會發生錯誤,無法通過編譯

  • 執行時異常

    • 都是RuntimeException類及其子類

    • 無需顯示處理,也可以和編譯時異常一樣處理

  • 圖示

3.3 JVM預設處理異常的方式(理解)

  • 如果程式出現了問題,我們沒有做任何處理,最終JVM 會做預設的處理,處理方式有如下兩個步驟:

    • 把異常的名稱,錯誤原因及異常出現的位置等資訊輸出在了控制檯

    • 程式停止執行

3.4 檢視異常資訊 (理解)

控制檯在列印異常資訊時,會列印異常類名,異常出現的原因,異常出現的位置

我們調bug時,可以根據提示,找到異常出現的位置,分析原因,修改異常程式碼

3.5 throws方式處理異常(應用)

  • 定義格式

    public void 方法() throws 異常類名 {

    }
  • 示例程式碼

    public class ExceptionDemo {
    public static void main(String[] args) throws ParseException{
    System.out.println("開始");
    // method();
    method2();

    System.out.println("結束");
    }

    //編譯時異常
    public static void method2() throws ParseException {
    String s = "2048-08-09";
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    Date d = sdf.parse(s);
    System.out.println(d);
    }

    //執行時異常
    public static void method() throws ArrayIndexOutOfBoundsException {
    int[] arr = {1, 2, 3};
    System.out.println(arr[3]);
    }
    }
  • 注意事項

    • 這個throws格式是跟在方法的括號後面的

    • 編譯時異常必須要進行處理,兩種處理方案:try...catch …或者 throws,如果採用 throws 這種方案,在方法上進行顯示宣告,將來誰呼叫這個方法誰處理

    • 執行時異常因為在執行時才會發生,所以在方法後面可以不寫,執行時出現異常預設交給jvm處理

3.6 throw丟擲異常 (應用)

  • 格式

    throw new 異常();

  • 注意

    這個格式是在方法內的,表示當前程式碼手動丟擲一個異常,下面的程式碼不用再執行了

  • throws和throw的區別

    THROWSTHROW
    用在方法聲明後面,跟的是異常類名 用在方法體內,跟的是異常物件名
    表示宣告異常,呼叫該方法有可能會出現這樣的異常 表示手動丟擲異常物件,由方法體內的語句處理
  • 示例程式碼

    public class ExceptionDemo8 {
    public static void main(String[] args) {
    //int [] arr = {1,2,3,4,5};
    int [] arr = null;
    printArr(arr);//就會 接收到一個異常.
    //我們還需要自己處理一下異常.
    }

    private static void printArr(int[] arr) {
    if(arr == null){
    //呼叫者知道成功列印了嗎?
    //System.out.println("引數不能為null");
    throw new NullPointerException(); //當引數為null的時候
    //手動建立了一個異常物件,拋給了呼叫者,產生了一個異常
    }else{
    for (int i = 0; i < arr.length; i++) {
    System.out.println(arr[i]);
    }
    }
    }

    }

3.7 try-catch方式處理異常(應用)

  • 定義格式

    try {
    	可能出現異常的程式碼;
    } catch(異常類名 變數名) {
    	異常的處理程式碼;
    }
  • 執行流程

    • 程式從 try 裡面的程式碼開始執行

    • 出現異常,就會跳轉到對應的 catch 裡面去執行

    • 執行完畢之後,程式還可以繼續往下執行

  • 示例程式碼

    public class ExceptionDemo01 {
        public static void main(String[] args) {
            System.out.println("開始");
            method();
            System.out.println("結束");
        }
    
        public static void method() {
            try {
                int[] arr = {1, 2, 3};
                System.out.println(arr[3]);
                System.out.println("這裡能夠訪問到嗎");
            } catch (ArrayIndexOutOfBoundsException e) {
                System.out.println("你訪問的陣列索引不存在,請回去修改為正確的索引");
            }
        }
    }
  • 注意

    1. 如果 try 中沒有遇到問題,怎麼執行?

      會把try中所有的程式碼全部執行完畢,不會執行catch裡面的程式碼

    2. 如果 try 中遇到了問題,那麼 try 下面的程式碼還會執行嗎?

      那麼直接跳轉到對應的catch語句中,try下面的程式碼就不會再執行了當catch裡面的語句全部執行完畢,表示整個體系全部執行完全,繼續執行下面的程式碼

    3. 如果出現的問題沒有被捕獲,那麼程式如何執行?

      那麼try...catch就相當於沒有寫.那麼也就是自己沒有處理.預設交給虛擬機器處理.

    4. 同時有可能出現多個異常怎麼處理?

      出現多個異常,那麼就寫多個catch就可以了.注意點:如果多個異常之間存在子父類關係.那麼父類一定要寫在下面

3.8 Throwable成員方法(應用)

  • 常用方法

    方法名說明
    public String getMessage() 返回此 throwable 的詳細訊息字串
    public String toString() 返回此可丟擲的簡短描述
    public void printStackTrace() 把異常的錯誤資訊輸出在控制檯
  • 示例程式碼

    public class ExceptionDemo02 {
        public static void main(String[] args) {
            System.out.println("開始");
            method();
            System.out.println("結束");
        }
    
        public static void method() {
            try {
                int[] arr = {1, 2, 3};
                System.out.println(arr[3]); //new ArrayIndexOutOfBoundsException();
                System.out.println("這裡能夠訪問到嗎");
            } catch (ArrayIndexOutOfBoundsException e) { //new ArrayIndexOutOfBoundsException();
    //            e.printStackTrace();
    
                //public String getMessage():返回此 throwable 的詳細訊息字串
    //            System.out.println(e.getMessage());
                //Index 3 out of bounds for length 3
    
                //public String toString():返回此可丟擲的簡短描述
    //            System.out.println(e.toString());
                //java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
    
                //public void printStackTrace():把異常的錯誤資訊輸出在控制檯
                e.printStackTrace();
    //            java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
    //            at com.itheima_02.ExceptionDemo02.method(ExceptionDemo02.java:18)
    //            at com.itheima_02.ExceptionDemo02.main(ExceptionDemo02.java:11)
    
            }
        }
    }

3.9 異常的練習 (應用)

  • 需求

    鍵盤錄入學生的姓名和年齡,其中年齡為18 - 25歲,超出這個範圍是異常資料不能賦值.需要重新錄入,一直錄到正確為止

  • 實現步驟

    1. 建立學生物件

    2. 鍵盤錄入姓名和年齡,並賦值給學生物件

    3. 如果是非法資料就再次錄入

  • 程式碼實現

    學生類

    public class Student {
        private String name;
        private int age;
    
        public Student() {
        }
    
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            if(age >= 18 && age <= 25){
                this.age = age;
            }else{
                //當年齡不合法時,產生一個異常
                throw new RuntimeException("年齡超出了範圍");
            }
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

    測試類

    public class ExceptionDemo12 {
        public static void main(String[] args) {
            // 鍵盤錄入學生的姓名和年齡,其中年齡為 18 - 25歲,
            // 超出這個範圍是異常資料不能賦值.需要重新錄入,一直錄到正確為止。
    
            Student s = new Student();
    
            Scanner sc = new Scanner(System.in);
            System.out.println("請輸入姓名");
            String name = sc.nextLine();
            s.setName(name);
           while(true){
               System.out.println("請輸入年齡");
               String ageStr = sc.nextLine();
               try {
                   int age = Integer.parseInt(ageStr);
                   s.setAge(age);
                   break;
               } catch (NumberFormatException e) {
                   System.out.println("請輸入一個整數");
                   continue;
               } catch (AgeOutOfBoundsException e) {
                   System.out.println(e.toString());
                   System.out.println("請輸入一個符合範圍的年齡");
                   continue;
               }
               /*if(age >= 18 && age <=25){
                   s.setAge(age);
                   break;
               }else{
                   System.out.println("請輸入符合要求的年齡");
                   continue;
               }*/
           }
            System.out.println(s);
    
        }
    }

3.10 自定義異常(應用)

  • 自定義異常概述

    當Java中提供的異常不能滿足我們的需求時,我們可以自定義異常

  • 實現步驟

    1. 定義異常類

    2. 寫繼承關係

    3. 提供空參構造

    4. 提供帶參構造

  • 程式碼實現

    異常類

    public class AgeOutOfBoundsException extends RuntimeException {
        public AgeOutOfBoundsException() {
        }
    
        public AgeOutOfBoundsException(String message) {
            super(message);
        }
    }

    學生類

    public class Student {
        private String name;
        private int age;
    
        public Student() {
        }
    
        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            if(age >= 18 && age <= 25){
                this.age = age;
            }else{
                //如果Java中提供的異常不能滿足我們的需求,我們可以使用自定義的異常
                throw new AgeOutOfBoundsException("年齡超出了範圍");
            }
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

    測試類

    public class ExceptionDemo12 {
        public static void main(String[] args) {
            // 鍵盤錄入學生的姓名和年齡,其中年齡為 18 - 25歲,
            // 超出這個範圍是異常資料不能賦值.需要重新錄入,一直錄到正確為止。
    
            Student s = new Student();
    
            Scanner sc = new Scanner(System.in);
            System.out.println("請輸入姓名");
            String name = sc.nextLine();
            s.setName(name);
           while(true){
               System.out.println("請輸入年齡");
               String ageStr = sc.nextLine();
               try {
                   int age = Integer.parseInt(ageStr);
                   s.setAge(age);
                   break;
               } catch (NumberFormatException e) {
                   System.out.println("請輸入一個整數");
                   continue;
               } catch (AgeOutOfBoundsException e) {
                   System.out.println(e.toString());
                   System.out.println("請輸入一個符合範圍的年齡");
                   continue;
               }
               /*if(age >= 18 && age <=25){
                   s.setAge(age);
                   break;
               }else{
                   System.out.println("請輸入符合要求的年齡");
                   continue;
               }*/
           }
            System.out.println(s);
    
        }
    }

                         擴充套件練習

程式設計題(時間日期相關)

題目1

請在控制檯以“xxxx年xx月xx日 xx時xx分xx秒”的格式列印當前系統時間。

要求:

1:使用Date+SimpleDateFormat完成一遍,

2:再使用LocalDateTime+DateTimeFormatter完成一遍;

提示:

獲取當前時間物件之後,直接利用格式化工具格式化即可;

參考程式碼:

 package day6.No_1;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

public class Demo {
public static void main(String[] args) {
Date date =new Date();
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy年MM月dd日 HH時mm分ss秒");
System.out.println(simpleDateFormat.format(date));
LocalDateTime time = LocalDateTime.now();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH時mm分ss秒");
System.out.println(time.format(dateTimeFormatter));

}
}

題目2

請輸入“您的生日”,格式:yyyy-MM-dd,使用程式計算您已經來到這個世界多少天了。

提示:

本題利用JDK8中的LocalDate加DateTimeFormatter和Period即可實現;

效果演示:

參考程式碼:

package day6.No_2;

import java.time.LocalDate;
import java.time.Period;

public class Demo {
public static void main(String[] args) {
LocalDate localDate = LocalDate.of(1999, 11, 25);
LocalDate localDate1 = LocalDate.of(2020, 11, 8);
Period between = Period.between(localDate, localDate1);
int years = between.getYears();//獲取年
int months = between.getMonths();//獲取月
int days = between.getDays();//獲取天
System.out.println("你已經來這個世界"+years+"年零 "+months+"月零 "+days+"天");
}
}

題目3

請從控制檯分別接收兩個“生日”,格式為:yyyy年MM月dd日,用程式比較兩個生日表示的人的年齡大小關係並打印出結果;

要求:

1:使用Date+SimpleDateFormat完成一遍,

2:再使用LocalDate+DateTimeFormatter完成一遍;

提示:

注意,生日值越小,證明出生的越早,就意味著年齡越大,不要搞反了呦;

執行結果:

參考程式碼:

package day6.No_3;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Scanner;
import java.util.Timer;

/*
鍵盤錄入字串
使用Date/Loca將字串轉換為毫秒
對比二者毫秒值
*/
public class Demo {
public static void main(String[] args) throws ParseException {

Scanner sc = new Scanner(System.in);
System.out.println("請輸入第一個生日(****年**月**日)");
String s1 = sc.next();
System.out.println("請輸入第一個生日(****年**月**日)");
String s2 = sc.next();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
LocalDate localDate = LocalDate.parse(s1, dateTimeFormatter);
LocalDate localDate1 = LocalDate.parse(s2, dateTimeFormatter);
// LocalDate+DateTimeFormatter實現對比
if (localDate.isAfter(localDate1)) {
System.out.println("第二個大");
}
if (localDate.isBefore(localDate1)) {
System.out.println("第一個大");
}if (localDate.isEqual(localDate1)){
System.out.println("一樣大");
}

// Date SimpleDateFormat實現對比:

Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
try {
long time1 = simpleDateFormat.parse(s1).getTime();
long time2 = simpleDateFormat.parse(s2).getTime();
if (time1 > time2) {
System.out.println("第二個大");
} else if (time1<time2){
System.out.println("第一個大");
}else {
System.out.println("一樣大");
}
} catch (ParseException e) {
e.printStackTrace();
}
}
}

程式設計題(異常)

題目1

按要求補全程式碼,使main方法能夠正常執行到結束;

public static void main(String[] args){
int[] arr = new int[0];
//提示:下面這一行程式碼會導致方法內丟擲“空指標異常”,需要你補充一些程式碼,使讓程式繼續執行
int n1 = getMax(null);
//提示:下面這一行程式碼會導致方法內丟擲“索引越界異常”,需要你補充一些程式碼,使讓程式繼續執行
int n2 = getMax(arr);
int[] arr2 = {1,2,4,24,32,5324,32};
int n3 = getMax(arr2);
System.out.println("程式終於執行完了...");
}
//獲取陣列最大值
public static int getMax(int[] args){
int max = args[0];
for(int i = 1 ; i < args.length ; i++){
if(max < args[i]){
max = args[i];
}
}
return max;
}

提示:

可以利用異常的技術,捕獲程式中的異常,然後可以讓程式繼續執行;

效果:

參考程式碼:

package day6.No_4;

public class Demo {
public static void main(String[] args){
int[] arr = new int[0];
//提示:下面這一行程式碼會導致方法內丟擲“空指標異常”,需要你補充一些程式碼,使讓程式繼續執行
try {
int n1 = getMax(null);
} catch (NullPointerException e) {
System.out.println("捕獲了一個空指標...程式繼續執行");
}
//提示:下面這一行程式碼會導致方法內丟擲“索引越界異常”,需要你補充一些程式碼,使讓程式繼續執行
try {
int n2 = getMax(arr);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("捕獲了索引越界異常...程式繼續");
}
int[] arr2 = {1,2,4,24,32,5324,32};
int n3 = getMax(arr2);
System.out.println("程式終於執行完了...");
}
//獲取陣列最大值
public static int getMax(int[] args){
int max = args[0];
for(int i = 1 ; i < args.length ; i++){
if(max < args[i]){
max = args[i];
}
}
return max;
}
}

題目2

請從控制檯接收兩個整數並計算兩個數的商,使用程式控制,如果使用者輸入的不是整數,則提示使用者重新輸入;

提示:

注意:如果我們使用nextInt方法讓使用者輸入整數,但使用者實際輸入的不是整數的時候,會發生異常,而對於一個鍵盤輸入物件來說,一旦發生異常,即使使用try{}catch(){}語句進行了處理,這個鍵盤輸入物件也無法繼續工作了,解決的辦法就是重寫建立新的鍵盤輸入物件即可;

效果:

參考程式碼:

package day6.No_5;

import java.math.BigDecimal;
import java.util.InputMismatchException;
import java.util.Scanner;

public class Demo {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
while (true) {
try {
sc=new Scanner(System.in);
System.out.println("請輸入第一個整數:");
int i1 = sc.nextInt();
System.out.println("請輸入第二個整數:");
int i2 = sc.nextInt();
System.out.println(i1 + "除以" + i2 + "=" + (i1 / i2));
break;
} catch (InputMismatchException e) {
System.out.println("請輸入整數");
}
}

}
}

題目3

自定義一個鍵盤輸入的工具類,提供3個靜態方法,分別完成讓使用者輸入整數,小數,和字串的功能,且當用戶輸入錯誤的時候,不能結束程式,要給使用者重新輸入的機會;

提示:

其實就是把上一題中處理異常和鍵盤輸入的程式碼抽取出來,形成一個獨立的工具類即可;

效果:

參考程式碼:

package day6.No_6;

import java.util.InputMismatchException;
import java.util.Scanner;

public class Demo {
public static void main(String[] args) {
int num = Num();
System.out.println("整數為:"+num);
Double xiaoshu = Xiaoshu();
System.out.println("小數為:"+xiaoshu);
String zifu = Zifu();
System.out.println("字元為:"+zifu);


}

public static int Num() {
Scanner sc = new Scanner(System.in);
while (true) {
sc = new Scanner(System.in);
System.out.println("請輸入整數:");
try {
int anInt = sc.nextInt();
return anInt;
} catch (Exception e) {
System.out.println("必須為整數");
}
}
}

public static Double Xiaoshu() {
Scanner sc = new Scanner(System.in);
while (true) {
sc = new Scanner(System.in);
System.out.println("請輸入小數:");
try {
Double andouble = sc.nextDouble();
return andouble;
} catch (Exception e) {
System.out.println("必須為小數");
}
}
}

public static String Zifu() {
Scanner sc = new Scanner(System.in);
sc = new Scanner(System.in);
System.out.println("請輸入字元:");
String s = sc.next();
return s;

}
}