JavaSE第14篇:常用API、異常

核心概述:本篇我們還是將繼續(xù)學(xué)習(xí)常用的API,其中有用于一些基本數(shù)學(xué)運算的工具類Math、任意精度的整數(shù)BigInteger類、超大浮點數(shù)據(jù)BigDecimal;此外,在程序開發(fā)的過程中,我們常常會遇到各種各樣的異?,F(xiàn)象,所以在本篇我們也將會學(xué)習(xí)認(rèn)識并處理java中的異常。

第一章:Math類

1.1-概述(了解)

java.lang.Math 類包含用于執(zhí)行基本數(shù)學(xué)運算的方法,如初等絕對值、四舍五入等。類似這樣的工具類,其所有方法均為靜態(tài)方法,并且不會創(chuàng)建對象,調(diào)用起來非常簡單。

1.2-常用方法(記憶)

方法

image

代碼

  public static void main(String[] args) {
    System.out.println(Math.abs(-100));   // 100
    System.out.println(Math.ceil(10.1));  // 11.0
    System.out.println(Math.floor(10.1));  // 10.0
  }

第二章:BigInteger類

2.1-概述(了解)

java.math.BigInteger類,不可變的任意精度的整數(shù)。如果運算中,數(shù)據(jù)的范圍超過了long類型后,可以使用BigInteger類實現(xiàn),該類的計算整數(shù)是不限制長度的。

2.2-構(gòu)造方法(記憶)

BigInteger(String value) 將 BigInteger 的十進(jìn)制字符串表示形式轉(zhuǎn)換為 BigInteger。超過long類型的范圍,已經(jīng)不能稱為數(shù)字了,因此構(gòu)造方法中采用字符串的形式來表示超大整數(shù),將超大整數(shù)封裝成BigInteger對象。

2.3-常用方法(記憶)

方法

image

代碼

public static void main(String[] args){
    BigInteger big1 = new BigInteger("987654321123456789000");
    BigInteger big2 = new BigInteger("123456789987654321");
    //加法運算
    BigInteger add = big1.add(big2);
    System.out.println("求和:"+add);
    //減法運算
    BigInteger sub = big1.subtract(big2);
    System.out.println("求差:"+sub);
    //乘法運算
    BigInteger mul = big1.multiply(big2);
    System.out.println("乘積:"+mul);
    //除法運算
    BigInteger div = big1.divide(big2);
    System.out.println("除法:"+div);
}

第三章:BigDecimal類

3.1-概述(了解)

java.math.BigDecimal類,不可變的、任意精度的有符號十進(jìn)制數(shù)。該類可以實現(xiàn)超大浮點數(shù)據(jù)的精確運算。

3.2-構(gòu)造方法(記憶)

BigDecimal(String value)將 BigDecimal的十進(jìn)制字符串表示形式轉(zhuǎn)換為 BigDecimal。

3.3-常用方法(記憶)

方法

image

divide方法

  • BigDecimal divide(BigDecimal divisor,int scale,int roundingMode)
    • divesor:此 BigDecimal 要除以的值。
    • scale:保留的位數(shù)
    • roundingMode:舍入方式
  • 舍入方式:BigDecimal類提供靜態(tài)的成員變量來表示舍入的方式
    • BigDecimal.ROUND_UP 向上加1。
    • BigDecimal.ROUND_DOWN 直接舍去。
    • BigDecimal.ROUND_HALF_UP 四舍五入。

代碼

public static void main(String[] args){
      BigDecimal big1 = new BigDecimal("5.25");
      BigDecimal big2 = new BigDecimal("3.25");
      //加法計算
      BigDecimal add = big1.add(big2);
      System.out.println("求和:"+add);
      //減法計算
      BigDecimal sub = big1.subtract(big2);
      System.out.println("求差:"+sub);
      //乘法計算
      BigDecimal mul = big1.multiply(big2);
      System.out.println("乘法:"+mul);
      //除法計算
      BigDecimal div = big1.divide(big2,2,BigDecimal.ROUND_HALF_UP);
      System.out.println(div);
}

第四章:基本類型包裝類

4.1-概述(了解)

Java提供了兩個類型系統(tǒng),基本類型與引用類型,使用基本類型在于效率,然而很多情況,會創(chuàng)建對象使用,因為對象可以做更多的功能,如果想要我們的基本類型像對象一樣操作,就可以使用基本類型對應(yīng)的包裝類,如下:

image

4.2-Integer類(了解)

概述

包裝一個對象中的原始類型 int 的值。其構(gòu)造方法和靜態(tài)方法如下:

image

代碼

public static void main(String[] args) {
    //public Integer(int value):根據(jù) int 值創(chuàng)建 Integer 對象(過時)
    Integer i1 = new Integer(100);
    System.out.println(i1);

    //public Integer(String s):根據(jù) String 值創(chuàng)建 Integer 對象(過時)
    Integer i2 = new Integer("100");
    //Integer i2 = new Integer("abc"); //NumberFormatException
    System.out.println(i2);
    System.out.println("--------");

    //public static Integer valueOf(int i):返回表示指定的 int 值的 Integer 實例
    Integer i3 = Integer.valueOf(100);
    System.out.println(i3);

    //public static Integer valueOf(String s):返回一個保存指定值的Integer對象 String
    Integer i4 = Integer.valueOf("100");
    System.out.println(i4);
}

4.3-裝箱與拆箱(理解)

基本類型與對應(yīng)的包裝類對象之間,來回轉(zhuǎn)換的過程稱為”裝箱“與”拆箱“:

  • 裝箱:從基本類型轉(zhuǎn)換為對應(yīng)的包裝類對象。
  • 拆箱:從包裝類對象轉(zhuǎn)換為對應(yīng)的基本類型。

用Integer與 int為例:(看懂代碼即可)

基本數(shù)值---->包裝對象

Integer i = new Integer(4);//使用構(gòu)造函數(shù)函數(shù)
Integer iii = Integer.valueOf(4);//使用包裝類中的valueOf方法

包裝對象---->基本數(shù)值

int num = i.intValue();

4.4-自動裝箱與拆箱(理解)

由于我們經(jīng)常要做基本類型與包裝類之間的轉(zhuǎn)換,從Java 5(JDK 1.5)開始,基本類型與包裝類的裝箱、拆箱動作可以自動完成。例如:

Integer i = 4;//自動裝箱。相當(dāng)于Integer i = Integer.valueOf(4);
i = i + 5;//等號右邊:將i對象轉(zhuǎn)成基本數(shù)值(自動拆箱) i.intValue() + 5;
//加法運算完成后,再次裝箱,把基本數(shù)值轉(zhuǎn)成對象。

4.5-基本類型與字符串互相轉(zhuǎn)換(記憶)

基本類型轉(zhuǎn)String

轉(zhuǎn)換方式:

  • 方式一:直接在數(shù)字后加一個空字符串
  • 方式二:通過String類靜態(tài)方法valueOf()

示例代碼:

public static void main(String[] args) {
    //int --- String
    int number = 100;
    //方式1
    String s1 = number + "";
    System.out.println(s1);
    //方式2
    //public static String valueOf(int i)
    String s2 = String.valueOf(number);
    System.out.println(s2);
}

String轉(zhuǎn)基本類型

除了Character類之外,其他所有包裝類都具有parseXxx靜態(tài)方法可以將字符串參數(shù)轉(zhuǎn)換為對應(yīng)的基本類型:

  • public static byte parseByte(String s):將字符串參數(shù)轉(zhuǎn)換為對應(yīng)的byte基本類型。
  • public static short parseShort(String s):將字符串參數(shù)轉(zhuǎn)換為對應(yīng)的short基本類型。
  • public static int parseInt(String s):將字符串參數(shù)轉(zhuǎn)換為對應(yīng)的int基本類型。
  • public static long parseLong(String s):將字符串參數(shù)轉(zhuǎn)換為對應(yīng)的long基本類型。
  • public static float parseFloat(String s):將字符串參數(shù)轉(zhuǎn)換為對應(yīng)的float基本類型。
  • public static double parseDouble(String s):將字符串參數(shù)轉(zhuǎn)換為對應(yīng)的double基本類型。
  • public static boolean parseBoolean(String s):將字符串參數(shù)轉(zhuǎn)換為對應(yīng)的boolean基本類型。

代碼:(以Integer為例)

public class Demo18WrapperParse {
    public static void main(String[] args) {
        int num = Integer.parseInt("100");
    }
}

第五章:認(rèn)識異常

5.1-什么是異常(了解)

異常,就是不正常的意思。在生活中:醫(yī)生說,你的身體某個部位有異常,該部位和正常相比有點不同,該部位的功能將受影響.在程序中的意思就是:

  • 異常 :指的是程序在執(zhí)行過程中,出現(xiàn)的非正常的情況,最終會導(dǎo)致JVM的非正常停止。(因程序問題而中斷程序執(zhí)行的現(xiàn)象。)

在Java等面向?qū)ο蟮木幊陶Z言中,異常本身是一個類,產(chǎn)生異常就是創(chuàng)建異常對象并拋出了一個異常對象。Java處理異常的方式是中斷處理。

需要注意的是:異常指的并不是語法錯誤,語法錯了,編譯不通過,不會產(chǎn)生字節(jié)碼文件,根本不能運行。

5.2-異常體系(理解)

image

在Java中,為了維護(hù)程序正常執(zhí)行,Java提供了處理異常的異常機制(異常類)。

在Java提供的異常機制中,其中java.lang.Throwable是根類,而根類的派生類有java.lang.Errorjava.lang.Excepiton兩個子類。

Error,錯誤(絕癥,比如:“癌癥”),該類型異常在程序中無法處理,只能盡量避免。

Excepiton,編譯期異常(寫源代碼時)(小毛病,比如:類似感冒),該類型異常在程序中是可處理的。Excepiton類型還有一個子類RunTimeException,表示運行期異常(程序運行的過程中),該類型異常在程序中也是可處理的。

為了更好的區(qū)分以上描述的異常分類,我們看以下程序。

// 【Error異?!?// Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
// 內(nèi)存溢出。超出了分配給JVM內(nèi)存大小。
// 該程序只能修改源代碼解決問題。
int[]nums = new int[1024*1024*1024];

// 【Exception異?!?SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
// Unhandled exception: java.text.ParseException
// 此處在編寫源代碼時就發(fā)生異常,該異常后續(xù)可以通過相關(guān)的處理機制處理和避免
Date date = format.parse("2083-10-10"); 

// 【RunTimeException異?!?int[] nums = {1,2,3};
// Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
// 在程序運行時出現(xiàn)的異常,數(shù)組下標(biāo)超出。該異??梢酝ㄟ^相關(guān)異常機制處理
System.out.println(nums[4]);

5.3-異常產(chǎn)生的過程(理解)

在編程中,為了更好的處理異常,我們首先要了解異常產(chǎn)生的過程。下面通過一段異常代碼來分析。

需求和代碼

  // 需求:定義一個方法,用來獲取指定數(shù)組的指定位置的元素
  public static void main(String[] args) {
    int[]nums = {1,2,3};
    System.out.println(getElement(nums,4));
  }
  public static int getElement(int[]arr,int index){
    return arr[index];
  }

分析

  • 在執(zhí)行g(shù)etElement方法的過程中,JVM檢測出數(shù)組索引越界異常,此時JVM會做兩件事:

    • 創(chuàng)建一個ArrayIndexOutOfBoundsException異常對象,該對象中包含了異常的信息(內(nèi)容、原因、位置)
    • 因為getElment方法中沒有異常處理,JVM會把異常對象拋給getElment方法的調(diào)用處-main方法。
  • main方法接收到了ArrayIndexOutOfBoundsException異常對象,也沒有處理異常,則會把異常對象拋給JVM

  • JVM接收到了main方法后,會做兩件事:

    • 在控制臺打印異常信息(內(nèi)容、原因、位置)
    • 終止程序的執(zhí)行

圖解

image

第六章:處理異常

6.1-異常關(guān)鍵字(記憶)

  • try
  • catch
  • finally
  • throw
  • throws

6.2-拋出異常throw(理解)

概述

在編寫程序時,我們必須要考慮程序出現(xiàn)問題的情況。比如,在定義方法時,方法需要接受參數(shù)。那么,當(dāng)調(diào)用方法使用接受到的參數(shù)時,首先需要先對參數(shù)數(shù)據(jù)進(jìn)行合法的判斷,數(shù)據(jù)若不合法,就應(yīng)該告訴調(diào)用者,傳遞合法的數(shù)據(jù)進(jìn)來。這時需要使用拋出異常的方式來告訴調(diào)用者。

在java中,提供了一個throw關(guān)鍵字,它用來拋出一個指定的異常對象。那么,拋出一個異常具體如何操作呢?

  1. 創(chuàng)建一個異常對象。封裝一些提示信息(信息可以自己編寫)。
  2. 需要將這個異常對象告知給調(diào)用者。怎么告知呢?怎么將這個異常對象傳遞到調(diào)用者處呢?通過關(guān)鍵字throw就可以完成。
    • throw用在方法內(nèi),用來拋出一個異常對象,將這個異常對象傳遞到調(diào)用者處,并結(jié)束當(dāng)前方法的執(zhí)行。

使用格式

throw new 異常類名(參數(shù));

代碼演示

public static void main(String[] args) {
    //創(chuàng)建一個數(shù)組 
    int[] arr = {2,4,52,2};
    //根據(jù)索引找對應(yīng)的元素 
    int index = 4;
    int element = getElement(arr, index);

    System.out.println(element);
    System.out.println("over");
}
  /*
   * 根據(jù) 索引找到數(shù)組中對應(yīng)的元素
   */
public static int getElement(int[] arr,int index){ 
    //判斷  索引是否越界
    if(index<0 || index>arr.length-1){
        /*
             判斷條件如果滿足,當(dāng)執(zhí)行完throw拋出異常對象后,方法已經(jīng)無法繼續(xù)運算。
             這時就會結(jié)束當(dāng)前方法的執(zhí)行,并將異常告知給調(diào)用者。這時就需要通過異常來解決。 
        */
        throw new ArrayIndexOutOfBoundsException("哥們,角標(biāo)越界了~~~");
    }
    int element = arr[index];
    return element;
}

注意:如果產(chǎn)生了問題,我們就會throw將問題描述類即異常進(jìn)行拋出,也就是將問題返回給該方法的調(diào)用者。

那么對于調(diào)用者來說,該怎么處理呢?一種是進(jìn)行捕獲處理,另一種就是繼續(xù)講問題聲明出去,使用throws聲明處理。

6.3-聲明異常throws(理解)

什么是聲明異常

將問題標(biāo)識出來,報告給調(diào)用者。如果方法內(nèi)通過throw拋出了編譯時異常,而沒有捕獲處理(稍后講解該方式),那么必須通過throws進(jìn)行聲明,讓調(diào)用者去處理。

關(guān)鍵字throws運用于方法聲明之上,用于表示當(dāng)前方法不處理異常,而是提醒該方法的調(diào)用者來處理異常(拋出異常).

聲明異常格式

修飾符 返回值類型 方法名(參數(shù)) throws 異常類名1,異常類名2…{   }  

聲明異常的代碼演示

public static void main(String[] args) throws FileNotFoundException {
    read("a.txt");
}

// 如果定義功能時有問題發(fā)生需要報告給調(diào)用者??梢酝ㄟ^在方法上使用throws關(guān)鍵字進(jìn)行聲明
public static void read(String path) throws FileNotFoundException {
    if (!path.equals("a.txt")) {//如果不是 a.txt這個文件 
        // 我假設(shè)  如果不是 a.txt 認(rèn)為 該文件不存在 是一個錯誤 也就是異常  throw
        throw new FileNotFoundException("文件不存在");
    }
}

throws用于進(jìn)行異常類的聲明,若該方法可能有多種異常情況產(chǎn)生,那么在throws后面可以寫多個異常類,用逗號隔開。

public static void main(String[] args) throws IOException {
    read("a.txt");
}

public static void read(String path)throws FileNotFoundException, IOException {
    if (!path.equals("a.txt")) {//如果不是 a.txt這個文件 
        // 我假設(shè)  如果不是 a.txt 認(rèn)為 該文件不存在 是一個錯誤 也就是異常  throw
        throw new FileNotFoundException("文件不存在");
    }
    if (!path.equals("b.txt")) {
        throw new IOException();
    }
}

6.4-捕獲異常try…catch (記憶)

throws聲明異常的弊端是:異常后續(xù)代碼無法執(zhí)行(因為交給了JVM,JVM會終止程序)。

try-catch可以讓調(diào)用者處理異常,并會繼續(xù)執(zhí)行后續(xù)程序。

try...catch格式

try{
     編寫可能會出現(xiàn)異常的代碼
}catch(異常類型  e){
     處理異常的代碼
     //記錄日志/打印異常信息/繼續(xù)拋出異常
}

如何獲取異常信息

Throwable類中定義了一些查看方法:

  • public String getMessage():獲取異常的描述信息,原因(提示給用戶的時候,就提示錯誤原因。

  • public String toString():獲取異常的類型和異常描述信息(不用)。

  • public void printStackTrace():打印異常的跟蹤棧信息并輸出到控制臺。

包含了異常的類型,異常的原因,還包括異常出現(xiàn)的位置,在開發(fā)和調(diào)試階段,都得使用printStackTrace。

代碼演示

  // 需求:定義一個讀取文件的方法,檢測文件的路徑和后綴名
  public static void main(String[] args)  {
    try{
      retFile("d.txt");
    }catch (Exception e) {
      e.printStackTrace();
    }
    System.out.println("后續(xù)代碼");
    /*
     執(zhí)行結(jié)果:
        java.io.IOException: 文件路徑錯誤
            at it.leilei.cn.demo01.Main01.retFile(Main01.java:27)
            at it.leilei.cn.demo01.Main01.main(Main01.java:12)
        后續(xù)代碼
    */


  }
  // 讀取文件的方法
  private static void retFile(String path) throws IOException {
    // 如果后綴名不是.txt則拋出
    if(!path.contains(".txt")){
      throw  new FileNotFoundException("文件后綴名不是.txt");
    }
    if(!path.contains("c:")) {
      throw  new IOException("文件路徑錯誤");
    }
  }

6.5-finally代碼塊(記憶)

為什么要使用finally代碼塊

finally:有一些特定的代碼無論異常是否發(fā)生,都需要執(zhí)行。另外,因為異常會引發(fā)程序跳轉(zhuǎn),導(dǎo)致有些語句執(zhí)行不到。而finally就是解決這個問題的,在finally代碼塊中存放的代碼都是一定會被執(zhí)行的。

什么時候的代碼必須最終執(zhí)行

當(dāng)我們在try語句塊中打開了一些物理資源(磁盤文件/網(wǎng)絡(luò)連接/數(shù)據(jù)庫連接等),我們都得在使用完之后,最終關(guān)閉打開的資源。

語法格式

try{
     編寫可能會出現(xiàn)異常的代碼
}catch(異常類型  e){
     處理異常的代碼
     //記錄日志/打印異常信息/繼續(xù)拋出異常
}
...
finally{
    // 代碼塊
}

代碼演示

// 需求:定義一個讀取文件的方法,檢測文件的路徑和后綴名
  public static void main(String[] args)  {
    try{
      retFile("d.txt");
    }catch (Exception e) {
      e.printStackTrace();
    }finally {
      System.out.println("釋放資源");
    }
    System.out.println("后續(xù)代碼");


  }
  // 讀取文件的方法
  private static void retFile(String path) throws IOException {
    // 如果后綴名不是.txt則拋出
    if(!path.contains(".txt")){
      throw  new FileNotFoundException("文件后綴名不是.txt");
    }
    if(!path.contains("c:")) {
      throw  new IOException("文件路徑錯誤");
    }
  }

6.6-異常注意事項(了解)

注意事項

  • 運行時異常被拋出可以不處理。即不捕獲也不聲明拋出。

  • 如果父類拋出了多個異常,子類覆蓋父類方法時,只能拋出相同的異?;蛘呤撬淖蛹?/p>

  • 父類方法沒有拋出異常,子類覆蓋父類該方法時也不可拋出異常。此時子類產(chǎn)生該異常,只能捕獲處理,不能聲明拋出

  • 當(dāng)多異常處理時,捕獲處理,前邊的類不能是后邊類的父類

  • 在try/catch后可以追加finally代碼塊,其中的代碼一定會被執(zhí)行,通常用于資源回收。

  • 多個異常使用捕獲又該如何處理呢?

    1. 多個異常分別處理。
    2. 多個異常一次捕獲,多次處理。
    3. 多個異常一次捕獲一次處理。

多個異常常用方式

try{
     編寫可能會出現(xiàn)異常的代碼
}catch(異常類型A  e){  當(dāng)try中出現(xiàn)A類型異常,就用該catch來捕獲.
     處理異常的代碼
     //記錄日志/打印異常信息/繼續(xù)拋出異常
}catch(異常類型B  e){  當(dāng)try中出現(xiàn)B類型異常,就用該catch來捕獲.
     處理異常的代碼
     //記錄日志/打印異常信息/繼續(xù)拋出異常
}

第七章:自定義異常類

3.1 為什么要自定義異常類(了解)

? 我們說了Java中不同的異常類,分別表示著某一種具體的異常情況,那么在開發(fā)中總是有些異常情況是SUN沒有定義好的,此時我們根據(jù)自己業(yè)務(wù)的異常情況來定義異常類。例如年齡負(fù)數(shù)問題,考試成績負(fù)數(shù)問題等等。

3.2 什么是自定義異常類(了解)

? 在開發(fā)中根據(jù)自己業(yè)務(wù)的異常情況來定義異常類.

? 自定義一個業(yè)務(wù)邏輯異常: RegisterException。一個注冊異常類。

3.3 如何定義異常類(記憶)

  1. 自定義一個編譯期異常: 自定義類 并繼承于 java.lang.Exception 。
  2. 自定義一個運行時期的異常類:自定義類 并繼承于 java.lang.RuntimeException 。

3.4 代碼演示(練習(xí))

要求:我們模擬注冊操作,如果用戶名已存在,則拋出異常并提示:親,該用戶名已經(jīng)被注冊。

自定義異常類:

public class RegisterException extends Exception{
  public RegisterException(){
      super();
  }
  public RegisterException(String message){
      super(message);
  }

}

測試:

  public static void main(String[] args)  {
    // 接收用戶注冊的用戶名
    String name = new Scanner(System.in).next();
    try{
      check(name);
    }catch (RegisterException e){
      e.printStackTrace();
      return;
    }
    System.out.println("注冊成功");
  }

  public static void check(String n) throws RegisterException{
    String[]users={"張三","李四","王五"};
    for (int i = 0; i < users.length; i++) {
      if (n.equals( users[i])) {
        throw new RegisterException("親,該用戶名已經(jīng)注冊");
      }
    }
  }
 
image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容