<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Java的基本使用之異常處理

      1、Java中異常的基本概念

      異常是一種類,因此它本身帶有類型信息。異常可以在任何地方拋出,但只需要在上層捕獲。

      在 Java 中拋出異常的目的是為了在代碼執行發生錯誤的時候,停止,或者進行處理,以及拋出信息幫助程序員定位出現bug的位置。所以,我們需要在可能發生異常的地方拋出異常并進行捕獲處理。

      Java 中異常的繼承關系如下:

      由上圖可知,Throwable是異常體系的根,它繼承自Object。

      所有異常都可以調用 e.printStackTrace() 方法進行簡單打印輸出。

      1.1、Error 和 Exception

      Throwable有兩個體系:ErrorException。

      1.1.1、Error

      Error表示嚴重的錯誤,程序對此一般無能為力,例如:

      • OutOfMemoryError:內存耗盡
      • NoClassDefFoundError:無法加載某個Class
      • StackOverflowError:棧溢出

      1.1.2、Exception

      Exception則是運行時的錯誤,它可以被捕獲并處理。

      Exception分為兩大類:

      1. RuntimeException以及它的子類;
      2. RuntimeException(包括IOExceptionReflectiveOperationException等等)

       

      1.3、哪些異常需要被捕獲

      有些異常是應用程序邏輯處理的一部分,應該捕獲并處理。例如:

      • NumberFormatException:數值類型的格式錯誤
      • FileNotFoundException:未找到文件
      • SocketException:讀取網絡失敗

      還有一些異常是程序邏輯編寫不對造成的,應該修復程序本身。例如:

      • NullPointerException:對某個null的對象調用方法或字段。空指針異常,如果一個對象為null,調用其方法或訪問其字段就會產生NullPointerException。指針這個概念實際上源自C語言,Java語言中并無指針。我們定義的變量實際上是引用,Null Pointer更確切地說是Null Reference,
      • IndexOutOfBoundsException:數組索引越界

      Java規定:

      • 必須捕獲的異常:包括Exception及其子類,但不包括RuntimeException及其子類,這種類型的異常稱為Checked Exception。

      • 不需要捕獲的異常:包括Error及其子類,RuntimeException及其子類。

       

      2、捕獲異常(try{...} catch(){...})

      在Java中,凡是可能拋出異常的語句,都可以用try ... catch進行捕獲。通過捕獲異常就可以針對異常情況做操作,并且避免后面的程序被中斷。

      只要是在方法拋出的 Checked Exception,如果不在該方法的調用層捕獲,那就應該拋出來,然后在更高的調用層捕獲。所有未捕獲的異常,最終也必須在main()方法中捕獲或者在 main 方法中拋出然后由 JVM 進行處理,否則會編譯報錯。main()方法是最后捕獲異常的機會,不推薦在 main 方法中拋出異常。

      在捕獲了異常后我們應該進行相應的操作,至少應該打印記錄異常。

      public static void main(String[] args) {
          try {
              ...
          } catch (Exception e) {
              e.printStackTrace();
          }
      }

       

      我們可以使用多個 catch 語句,每個catch分別捕獲對應的Exception及其子類。JVM在捕獲到異常后,會從上到下匹配catch語句,匹配到某個catch后,執行catch代碼塊,然后不再繼續匹配。簡單地說就是多個catch語句只有一個能被執行。

      存在多個catch的時候,子類必須寫在前面,否則永遠捕獲不到該子類異常。

      public static void main(String[] args) {
          try {
              process1();
          } catch (UnsupportedEncodingException e) {         //子類應該寫在前面,否則永遠捕獲不到
              System.out.println("Bad encoding");
          } catch (IOException | NumberFormatException e) {  //處理不同異常的代碼一樣時,我們可以用 | 把它們寫在一起
              System.out.println("Bad input");
          } 
      }

       

      2.1、finally 語句

      Java 的try ... catch機制還提供了finally語句,finally語句塊保證有無錯誤都會執行。

      public static void main(String[] args) {
          try {
              ...
          } catch (Exception e) {
              e.printStackTrace();
          } finally {
              System.out.println("END");
          }
      }

      finally 語句不是必須的,可寫可不寫,并且它總是最后執行的,finally 語句是用來保證一些代碼必須執行的。

      你也可以只使用try ... finally,而不寫catch語句,例如:

      //下面方法聲明了可能拋出的異常,所以可以不寫catch。
      void process(String file) throws IOException {
          try {
              ...
          } finally {
              System.out.println("END");
          }
      }

       

      在catch語句塊中拋出異常,finally語句仍然會執行:

      public class Main {
          public static void main(String[] args) {
              try {
                  Integer.parseInt("abc");
              } catch (Exception e) {
                  System.out.println("catched");
                  throw new RuntimeException(e);
              } finally {
                  System.out.println("finally");
              }
          }
      }
      
      //上述代碼執行結果如下:
      catched
      finally
      Exception in thread "main" java.lang.RuntimeException: java.lang.NumberFormatException: For input string: "abc"
          at Main.main(Main.java:8)
      Caused by: java.lang.NumberFormatException: For input string: "abc"
          at ...

      先打印了catched,后打印finally,然后再輸出異常信息。說明先執行了catch語句,然后又執行了finally語句塊,最后才拋出了異常并且在 JVM 中捕獲。因此,在catch中拋出異常,不會影響finally的執行。JVM會先執行finally,然后才拋出異常。

       

      3、拋出異常

      當某個方法拋出了異常時,如果在調用該方法時沒有捕獲異常,那就應該拋出來,由更上層來進行捕獲,以此類推,直到遇到某個try ... catch被捕獲為止。所有未捕獲的異常,最終也必須在main()方法中捕獲或者在 main 方法中拋出然后由 JVM 進行處理,否則會編譯報錯。

      3.1、如何拋出異常

      拋出異常分兩步:

      1. 創建某個Exception的實例;
      2. throw語句拋出。

      代碼示例:

      public void process2(String s) {
          if (s==null) {
              NullPointerException e = new NullPointerException("異常信息");
              throw e;
              //一般寫成一行即可
              throw new NullPointerException("異常信息");
          }
      }

      子類重寫父類的方法時,子類方法不能拋出比父類方法更大的異常。

       

      3.2、異常轉換

      如果一個方法使用 catch 捕獲了某個異常后,又在 catch 語句中拋出新的異常,此時就相當于把拋出的異常類型“轉換”了,此時如果在其他方法中捕獲新異常,舊異常的信息不會被捕獲到。

      public class Main {
          public static void main(String[] args) {
              try {
                  process1();
              } catch (Exception e) {  //此時輸出process1方法的異常,并不會輸出process2方法中的異常信息
                  e.printStackTrace();
              }
          }
      
          static void process1() {
              try {
                  process2();
              } catch (NullPointerException e) {  //捕獲process2方法的異常并轉換
                  throw new IllegalArgumentException();
              }
          }
      
          static void process2() {
              throw new NullPointerException();
          }
      }

      這樣新的異常就會丟失原始異常信息,我們無法看不到原始異常NullPointerException的信息。

      為了能追蹤到完整的異常棧,在構造異常的時候,把原始的Exception實例傳進去,新的Exception就可以持有原始Exception信息。對上述代碼改進如下:

      public class Main {
          public static void main(String[] args) {
              try {
                  process1();
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      
          static void process1() {
              try {
                  process2();
              } catch (NullPointerException e) {
                  throw new IllegalArgumentException(e);  //這里將原始的異常傳了進去
              }
          }
      
          static void process2() {
              throw new NullPointerException();
          }
      }
      
      //運行上述代碼,打印出的異常棧類似以下信息:
      //Caused by: Xxx,說明捕獲的IllegalArgumentException并不是造成問題的根源,根源在于NullPointerException,是在Main.process2()方法拋出的。
      java.lang.IllegalArgumentException: java.lang.NullPointerException
          at Main.process1(Main.java:15)
          at Main.main(Main.java:5)
      Caused by: java.lang.NullPointerException
          at Main.process2(Main.java:20)
          at Main.process1(Main.java:13)

      在代碼中獲取原始異常可以使用Throwable.getCause()方法。如果返回null,說明已經是“根異常”了。

      捕獲到異常并再次拋出時,一定要留住原始異常,否則很難定位第一案發現場!有了完整的異常棧的信息,我們才能快速定位并修復代碼的問題。

       

      4、打印異常信息(e.printStackTrace())

      所有異常都可以通過printStackTrace()打印出方法的調用棧,打印信息類似下面:

      java.lang.NumberFormatException: null
          at java.base/java.lang.Integer.parseInt(Integer.java:614)
          at java.base/java.lang.Integer.parseInt(Integer.java:770)
          at Main.process2(Main.java:16)
          at Main.process1(Main.java:12)
          at Main.main(Main.java:5)

      上述信息表示:NumberFormatException是在java.lang.Integer.parseInt方法中被拋出的,從下往上看,調用層次依次是:

      1. main()調用process1()
      2. process1()調用process2()
      3. process2()調用Integer.parseInt(String)
      4. Integer.parseInt(String)調用Integer.parseInt(String, int)

      每層調用都給出了源代碼的行號,可直接定位。

       

      5、使用日志(JDK Logging)

      日志就是Logging,它的目的是為了取代System.out.println()

      5.1、使用日志的好處

      1. 可以設置輸出樣式,避免自己每次都寫"ERROR: " + var
      2. 可以設置輸出級別,禁止某些級別輸出。例如,只輸出錯誤日志
      3. 可以被重定向到文件,存檔,這樣可以在程序運行結束后查看日志,便于追蹤問題
      4. 可以根據配置文件調整日志,無需修改代碼
      5. 可以按包名控制日志級別,只輸出某些包打的日志等等。。。

       

      5.2、如何使用日志

      Java 標準庫內置了日志包java.util.logging,我們可以直接用。

      import java.util.logging.Level;
      import java.util.logging.Logger;
      
      public class Hello {
          public static void main(String[] args) {
              Logger logger = Logger.getGlobal();
              logger.info("start process...");
              logger.warning("memory is running out...");
              logger.fine("ignored.");
              logger.severe("process will be terminated...");
          }
      }
      
      //打印以下信息:
      Mar 02, 2019 6:32:13 PM.Hello main  //自動打印出時間、調用類、調用方法等很多有用的信息。
      INFO: start process...
      Mar 02, 2019 6:32:13 PM.Hello main
      WARNING: memory is running out...
      Mar 02, 2019 6:32:13 PM.Hello main
      SEVERE: process will be terminated...

      上面的輸出當中,logger.fine()沒有打印。這是因為,日志的輸出可以設定級別。JDK 的 Logging 定義了7個日志級別,從嚴重到普通。默認級別是 INFO,INFO 級別以下的日志,不會被打印出來。使用日志級別的好處在于,調整級別,就可以屏蔽掉很多調試相關的日志輸出。

      日志級別如下:

      • SEVERE
      • WARNING
      • INFO
      • CONFIG
      • FINE
      • FINER
      • FINEST

      Java標準庫內置的Logging有以下局限:Logging系統在JVM啟動時讀取配置文件并完成初始化,一旦開始運行main()方法,就無法修改配置;配置不太方便,需要在JVM啟動時傳遞參數-Djava.util.logging.config.file=<config-file-name>。因此,Java標準庫內置的Logging使用并不是非常廣泛。

       

      6、使用 Commons Logging

      和Java標準庫提供的日志不同,Commons Logging是一個第三方日志庫,它可以掛接不同的日志系統,并通過配置文件指定掛接的日志系統。默認情況下,Commons Loggin自動搜索并使用Log4j,如果沒有找到Log4j,再使用JDK Logging。

      Commons Logging是一個第三方提供的庫,要想使用必須先把它下載下來,鏈接:https://commons.apache.org/proper/commons-logging/download_logging.cgi

      下載后,解壓,找到commons-logging-1.2.jar這個文件,將 jar 文件放在項目根目錄下,并且在 Libraries 中引入該 jar 文件,然后即可使用

      //先通過LogFactory獲取Log類的實例,然后使用Log實例的方法打日志
      import org.apache.commons.logging.Log;
      import org.apache.commons.logging.LogFactory;
      
      public class Main {
          public static void main(String[] args) {
              Log log = LogFactory.getLog(Main.class);
              log.info("start...");
              log.warn("end.");
          }
      }

      Commons Logging定義了6個日志級別,默認級別是INFO,即INFO級別以下的都不會打印出來

      • FATAL
      • ERROR
      • WARNING
      • INFO
      • DEBUG
      • TRACE

       

      7、使用 Log4j

      Log4j是一種非常流行的日志框架,Commons Logging可以作為“日志接口”來使用,而真正的“日志實現”可以使用Log4j。

      當我們使用 Log4j 輸出一條日志時,Log4j 自動通過不同的 Appender 把同一條日志輸出到不同的目的地

      使用Log4j的時候我們可以通過配置文件來讓 Log4j 讀取配置文件并按照我們的配置來輸出日志,例如:

      <?xml version="1.0" encoding="UTF-8"?>
      <Configuration>
          <Properties>
              <!-- 定義日志格式 -->
              <Property name="log.pattern">%d{MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36}%n%msg%n%n</Property>
              <!-- 定義文件名變量 -->
              <Property name="file.err.filename">log/err.log</Property>
              <Property name="file.err.pattern">log/err.%i.log.gz</Property>
          </Properties>
      <!-- 定義Appender,即目的地 --> <Appenders> <!-- 定義輸出到屏幕 --> <Console name="console" target="SYSTEM_OUT"> <!-- 日志格式引用上面定義的log.pattern --> <PatternLayout pattern="${log.pattern}" /> </Console> <!-- 定義輸出到文件,文件名引用上面定義的file.err.filename --> <RollingFile name="err" bufferedIO="true" fileName="${file.err.filename}" filePattern="${file.err.pattern}"> <PatternLayout pattern="${log.pattern}" /> <Policies> <!-- 根據文件大小自動切割日志 --> <SizeBasedTriggeringPolicy size="1 MB" /> </Policies> <!-- 保留最近10份 --> <DefaultRolloverStrategy max="10" /> </RollingFile> </Appenders>
      <Loggers> <Root level="info"> <!-- 對info級別的日志,輸出到console --> <AppenderRef ref="console" level="info" /> <!-- 對error級別的日志,輸出到err,即上面定義的RollingFile --> <AppenderRef ref="err" level="error" /> </Root> </Loggers> </Configuration>

      有了配置文件還不夠,因為Log4j也是一個第三方庫,我們需要從這里(https://www.liaoxuefeng.com/wiki/1252599548343744/1264739436350112)下載Log4j,解壓后,把以下3個jar包添加至項目依賴中

      • log4j-api-2.x.jar
      • log4j-core-2.x.jar
      • log4j-jcl-2.x.jar

      把Commons Logging 添加至項目依賴中,Commons Logging會自動發現并使用Log4j。要打印日志,只需要按Commons Logging的寫法寫即可,不需要改動任何代碼,就可以得到Log4j的日志輸出。

      在開發階段,始終使用Commons Logging接口來寫入日志,并且開發階段無需引入Log4j。如果需要把日志寫入文件, 只需要把正確的配置文件和Log4j相關的jar包放入classpath,就可以自動把日志切換成使用Log4j寫入,不需要修改任何代碼。

      參考:https://www.liaoxuefeng.com/wiki/1252599548343744/1264739436350112

       

      posted @ 2020-04-28 18:15  wenxuehai  閱讀(1283)  評論(0)    收藏  舉報
      //右下角添加目錄
      主站蜘蛛池模板: 久久精品一区二区日韩av| 日韩乱码人妻无码中文字幕视频 | 建阳市| 国产精品第一区亚洲精品| 亚洲人成电影网站 久久影视| 无码国模国产在线观看免费| 色综合网天天综合色中文| 午夜在线不卡| 精品无码国产一区二区三区AV| 国产精品无码dvd在线观看| 国产乱码日韩精品一区二区| 亚洲av日韩av综合在线观看| 国产日韩av二区三区| 开心婷婷五月激情综合社区| 久久99热只有频精品6狠狠| 亚洲首页一区任你躁xxxxx| 亚洲男人的天堂久久香蕉| 久久天天躁狠狠躁夜夜avapp | 美日韩精品综合一区二区| 一区二区不卡国产精品| 白嫩少妇无套内谢视频| 国产精品自拍视频我看看| 国内自拍偷拍一区二区三区| 久久久久国产精品人妻| 亚洲欧美v国产蜜芽tv| 亚洲精国产一区二区三区| 欧美日本在线一区二区三区| 中文字幕成人精品久久不卡| 老男人久久青草av高清| 天海翼激烈高潮到腰振不止| 一级片黄色一区二区三区| 丰满少妇被猛烈进出69影院| 欧美极品色午夜在线视频 | 风流老熟女一区二区三区| 成av免费大片黄在线观看| 国产91精品一区二区亚洲| 日韩av日韩av在线| 免费看成人毛片无码视频| 亚洲欧洲久久激情久av| 口爆少妇在线视频免费观看 | 亚洲精品综合第一国产综合|