異常與包
一、異常
1.1、異常體系
異常概述:在現實生活中,常常會遇到很多的問題;類似的,在java中也會出現種種的不正常情況,將這些不正常情況封裝成爲對象,就叫做異常。簡單說:異常就是問題在java中的體現。
就像人生病了,病可以分爲嚴重性疾病,例如:癌症;也可以分爲非嚴重性疾病,例如:感冒,上火。類似的,在java中的異常體系(Throwable)可以分爲嚴重性的異常(Error)和非嚴重性的異常(Exception)。無論Error還是Exception都具有一些共性,比如:不正常原因,引發原因;那麼根據共性抽取原則,java就把這些共性抽取到父類Throwable中。
Throwabla的兩個子類:1、Error:描述嚴重性問題,比如類不存在、內存溢出等等;
2、Exception:描述非嚴重性問題,可以通過try/catch/finally語句處理。下面主要就是要學習Exception異常。
由Throwable類提供的一些重要方法:
(1)、getMessage():獲取異常信息,返回字符串;
(2)、toString():獲取異常類名和異常信息,返回字符串;
(3)、printStackTrace()獲取異常類名、異常信息和異常出現的位置。返回值void;
(4)、printStackTrace(PrintStream s)將異常內容保存在日誌文件中,以便查閱。
異常的處理:異常可以通過try/catch/finally語句進行處理,格式爲:
try{需要被檢查的代碼;}catch(異常類型 變量){處理異常的代碼;}finally{…}
注意:try中檢測到異常會將異常對象傳遞給catch,catch捕獲到異常進行處理。
finally裏通常用來關閉資源。比如:數據庫資源,IO資源等。try是一個獨立的代碼塊,在其中定義的變量只在該變量塊中有效。如果在try以外繼續使用,需要在try建立引用。在try對其進行初始化。IO,Socket就會遇到。finally代碼塊一般都會執行到,除非前面執行了System.exit(0)。
throws與throw的區別:定義方法時,需要把出現的問題暴露給調用者,那麼用throws在函數上聲明,調用者必須處理,否則編譯通不過。當方法內部出現了某種情況,程序不能繼續運行,需要跳轉,那麼用throw把異常對象拋出。簡單說:throws用於暴露異常;throw用於拋出異常。
對異常處理的一些建議:
(1)、聲明多個異常時,建議聲明更爲具體的異常,這樣異常處理可以更加具體;
(2)、聲明瞭幾個異常,就對應幾個catch塊。如果多個catch塊中的異常出現繼承關係時,父類異常catch塊放在最下面。
(3)、進行catch處理時,catch中一定要定義具體處理方式,不要簡單定義一句e.printStackTrace(),也不要簡單書寫一條輸出語句。
下面代碼演示異常:
package itheima.day09;
//演示多異常的處理
public class ExceptionDemo2 {
public static void main(String[] args) {
Demo1 d = new Demo1();
// 異常的處理
try{
int x = d.div(1, 1);
System.out.println("x = "+x);
// 算術異常
}catch(ArithmeticException e1){
System.out.println(e1.toString());
System.out.println("被零除了");
// 數組角標越界異常
}catch(ArrayIndexOutOfBoundsException e2){
System.out.println(e2.toString());
System.out.println("數組角標越界了");
}
}
}
class Demo1{
// 有異常的方法,其實RuntimeException子類可以不聲明
int div(int a,int b)throws ArithmeticException,ArrayIndexOutOfBoundsException
{
int[] arr = new int[a];
System.out.println(arr[4]);
return a/b;
}
}
1.2、自定義異常
項目中會出現特有的問題,而這些問題並未被java封裝成異常對象;那麼這些特有的問題可以按照java對問題封裝的思想進行自定義的異常封裝;這就是自定義異常。
自定義異常時,自定義異常類必須繼承Exception類或其子類,如:RuntimeException。因爲只有異常體系中才具有處理問題的特性。
運行時異常:Exception類中有一個特殊的子類RuntimeException:運行時異常。如果在函數內拋出了運行時異常,函數上不用聲明,即使聲明瞭,調用者也不用進行處理,編譯一樣能通過。之所以不用聲明也不同處理編譯一樣通過,發生了RuntimeException程序再運行毫無意義,希望程序停止,讓程序員修改;比如:除數是0,時根本無法運行,希望程序停止。
編譯時異常:發生編譯時異常時,必須處理,否則,編譯通不過。Exception體系中除了RuntimeException及其子類都是編譯時異常。
下面代碼演示自定義異常與RuntimeException:
package itheima.day09;
/*
需求:有一個圓形和長方形,都可以獲取面積。
對應面積如果出現非法的數值,視爲獲取面積出現了問題,
問題通過異常來表示。
*/
//傳入了非法值,程序運行下去毫無意義,希望程序停止,繼承RuntimeException的子類ArithmeticException
class IllegalValueEXception extends ArithmeticException
{
// 程序出現負數的面積時,處理不了,必須修改代碼
IllegalValueEXception(String message){
super(message);
}
}
//圖形的接口
interface Shape{
void getArea();
}
//長方形的類
class Rec implements Shape
{
private double length,width;
Rec(double length,double width){
if(length<=0 || width <=0)
// 當出現非法值時,拋出異常
throw new IllegalValueEXception("程序出現非法值");
this.length = length;
this.width = width;
}
public void getArea(){
System.out.println(length*width);
}
}
//圓形
class Circle implements Shape
{
private double radius;
public static final double PI = 3.14;
Circle(double radius){
if(radius <=0)
// 當出現非法值時,拋出異常
throw new IllegalValueEXception("程序出現非法值");
this.radius = radius;
}
public void getArea(){
System.out.println(radius*PI);
}
}
public class ExceptionTest2 {
public static void main(String[] args) {
// RuntimeException子類異常本來可以不處理,其實除了修改代碼,別無選擇,這裏的處理只是提醒
try {
Rec r = new Rec(-7,9);
r.getArea();
Circle c = new Circle(3);
c.getArea();
} catch (IllegalValueEXception e) {
System.out.println(e.toString());
System.out.println("必須修改代碼");
}
System.out.println("over");
}
}
異常在子父類覆蓋關係中的體現:
(1)、如果父類方法拋出異常,子類的覆蓋方法只能拋出父類異常或者該異常的子類;
(2)、如果父類方法拋出多個異常,那麼子類覆蓋方法只能拋出父類異常的子集;
(3)、如果父類的方法沒有拋出異常,子類該方法中的異常只能try、catch處理。
之所以異常在子父類覆蓋關係中有上面三方面的限制,那是因爲多態,子類也是父類的一種,比如:狗既可以稱爲狗,也可以稱爲動物。假設有異常發生,在處理多態的方法時,有可能父類的方法沒有沒覆蓋,這時,很簡單:不存在異常的覆蓋問題。但當父類的方法被子類覆蓋後,要是子類方法拋出的異常大於父類被覆蓋的方法所拋出的異常,那麼顯然有些異常處理不到!這不符合Java語言的安全性,所以:子類在覆蓋父類的方法時,所拋出的異常不能大於父類中被覆蓋方法的異常。
簡單說:異常在子父類覆蓋關係中有限制,就是因爲多態!
下面代碼演示:
package itheima.day09;
/*演示異常子父類中的覆蓋關係*/
public class FuGaiException {
public static void main(String[] args) {
Test1 t = new Test1();
t.function(new Zi());
}
}
/*
Exception
|__AException
|__BException
|__CException
*/
class AException extends Exception
{
}
class BException extends AException
{
}
class CException extends Exception
{
}
class Fu{
void show()throws AException
{
}
}
class Zi extends Fu{
void show()throws BException
{
}
}
class Test1{
/*當Fu f = new Zi()時,多態,
那麼f.show()調用的是子類的show()方法,
假如子類show()方法聲明的異常比父類show()方法聲明的多,那麼在這裏顯然就有些不能處理到
所以爲了程序的擴展性,子類覆蓋方法的異常必須是父類方法異常的子集。
*/
void function(Fu f){
try{
f.show();
}catch(AException e){
e.getMessage();
}
}
}
二、包
2.1、包(package)
包的概述:在計算機中,兩個同名文件不能同時存在於同一文件夾下;當要存儲兩個同名文件時,可以把它們分別存儲在不同的文件夾下。在Java中也一樣,當有兩個同名文件時,可以用不同的包把它們分別存儲。包可以對文件進行分類管理,給類提供多層的命名空間。包類似於文件夾。
注意:包必須寫在程序的第一行;包名一般小寫,例如:package itheima.day09;;當加入了包後,類名的全稱爲:包名.類名;包也是一種封裝形式。
包的導入:導入包用關鍵字import,導入包可以簡化程序的書寫;包的導入並非導入包中的包,而是導入包中的類;一個程序文件中只有一個package,但可以有多個import,也就是說一個程序文件可以導入多個不同的包;“*”是包中類的通配符,意爲導入所有的包,但一般需要包中哪個類就導入哪個類,例如:importmypack.Demo;,而不是import mypack.*;,提高程序運行的效率。
權限:在java中,有四種權限修飾符:public(公有的),protected(保護的),default(默認的,不寫),private(私有的)。被訪問的包中的類權限必須是public的。具體權限如下圖:
classpath:是給java虛擬機(JVM)提供的一個環境變量,可以指定類或者包所在的路徑。
path和classpath的區別:
path環境變量裏面記錄的是可執行性文件,如.exe文件,對可執行文件先在當前路徑去找,如果沒找到就去path環境變量中配置的路徑去找,簡單說:path環境變量是配置給windows用的。
classpath環境變量裏記錄的是java類文件的所在的目錄,當沒配置classpath路徑,直接在當前路徑尋找;當配置了classpath路徑,結尾處不加分號,會在配置的路徑去尋找,若找不到直接報錯,結尾處加分號,先在配置路徑尋找,找不到再到當前路徑尋找,再找不到就報錯。
2.2、jar包
在windows中,可以把很多的文件壓縮成zip包;類似的,在java中,可以把很多的.class文件壓縮成jar包。jar包可以方便與於項目的攜帶。
在項目中,當需要用到第三方一共的jar包時,那麼需要先將jar包導入。
在eclipse中導入jar包:
1、點擊工程的根目錄,點擊Properties進入Properties;
2、在Properties頁面中選中Java Build Path,選中Libraries標籤,點擊Add External JARs;
3、找到需要添加的jar包,確定即可。