1. 程式人生 > >Java之內部類與異常類

Java之內部類與異常類

一、內部類

在一個類中定義另一個類,這樣的類成為內部類,包含內部類的類稱為 內部類的 外嵌類。

內部類與外嵌類的關係:

1.內部類可以呼叫其外嵌類的方法和成員變數

2.內部類中不可以宣告類變數和類方法

3.外嵌類可以 用內部類宣告的物件作為外嵌類的成員

4.內部類僅供其對應的外嵌類使用,其他類不可以宣告別的類的內部類物件。

public class RCF{
    static String from;
    //內部類的宣告
    class RedCow{
        String cown = "red";
        int h , w;
        RedCow(int H,int W){
            h = H;    w = W;
        }
        void speak(){
            System.out.println("Name:" + cown +"; Height:" + h 
                    + "; Weight:" + w + "; Family:" + from);
        }
    }
    RedCow cow;//內部類宣告物件
    RCF(String s){
        cow = new RedCow(152,100);
        from = s;
    }
    public void show(){
        cow.speak();
    }
}

public class neibulei {
    public static void main(String[] args) {
        RCF rcf = new RCF("andy");
        rcf.show();
        rcf.cow.speak();
//        RCF.RedCow rc = new RCF.RedCow(180, 150);
//        rc.speak();
    }

}

還記得static嗎?類成員和類變數,在這裡,內部類也可以被修飾為static內部類,即外嵌類中的一種靜態資料型別,用static修飾後,就可以在其他類中使用static內部類來建立物件

了。but,static內部類就不能操作外嵌類中的例項變數了,但可以操作類變數。即把上述中內部類RedCow改成static內部類後,main方法中的註釋部分就可以去掉了。

二、匿名類

匿名類,什麼是匿名類?沒有名字的類啊,那沒有名字的類怎麼來用呢?沒有名字肯定就不能宣告物件呀,但是卻可以直接建立物件的。那不能宣告物件,怎麼用這個匿名類呢? 那就作為引數來用呀!

匿名類有兩種,一種是與子類有關,一種是與介面有關

其實匿名類就是直接建立物件的啊,無論是與子類有關還是與介面有關,他都是沒有類名直接建立的。你看現在若有一個A類,那麼我們是如何建立他的物件的? A  a = new A();  這樣,就建立了一個A類的物件a,那現在我們是如何建立匿名類呢?  直接寫 new  A{  匿名類類體   };   這不就是直接建立了一個類嗎,這也就可以理解了匿名類是一個子類吧。也因為匿名類沒有名字可以用來宣告,所以常常直接建立一個匿名類物件  引數。

1.和子類有關的匿名類

匿名類的特點:

1.匿名類可以繼承和重寫父類的方法(匿名類就是一個子類)。

2.匿名類一定是內部類,因為他一定是在某個類中直接用匿名來建立物件的。

3.匿名類可以訪問外嵌類中的成員變數和方法,但是匿名類中不可以宣告static成員變數和static方法

 //抽象類物件

abstract class OutputAlphabet {
    public abstract void output();
}

//OutputAlphabet類的一個子類

public class OutputEnglish extends OutputAlphabet{
    public void output() {
        for(char c = 'a';c <= 'h';c++){
            System.out.printf("%3c",c);
        }
    }
}

public class ShowBoard {
    void showMess(OutputAlphabet show){  //引數是OutputAlphabet型別的物件
        show.output();
    }
}

public class nimig {
    public static void main(String[] args) {
        ShowBoard board = new ShowBoard();

//引數是一個OutputEnglish型別的物件,對於一個引數直接是一個物件我是有點不太理解的,他是怎麼用的呢?看下面,應該會容易理解一點
        board.showMess(new OutputEnglish());

//引數直接為物件不好理解,那我們先建立一個物件,然後再呼叫,是不是就明白了呢,其實道理也就是這樣的,不過是換了一種形式
        OutputEnglish english = new OutputEnglish();
        board.showMess(english);

        english.output(); // 這個,因為建立的物件裡有這個方法,所以直接呼叫也可以

// 這個,紅括號裡面的就是他的引數,前面可以宣告一個物件再來引用,但對於匿名類是不能宣告的,所以就直接作為引數,在這裡面進行建立、寫類體。注意一下匿名類是如何建立的:new 父類名(){      類體    }
        board.showMess ( new OutputAlphabet() {
            public void output() {   
//重寫父類方法
                for(char c = '1';c <= '5';c++){
                    System.out.printf("\n" + "%3c",c);
                }
            }
        }
)  ;   //注意分號不要忘了
    }
}

2.和介面有關的匿名類

與介面有關就是用介面名和類體來建立一個匿名類咯。  new  介面名 () {    類體    };

介面和類體組成的匿名類要求類體必須要重寫介面中的所有方法。

//介面定義

interface Speak{
    void sp();
}
class Hello{
    public void turn(Speak hello){  // 介面引數 
        hello.sp();
    }
}
public class niming {
    public static void main(String[] args) {
        Hello HD = new Hello();
        HD.turn ( new Speak(){ 
            public void sp(){
                System.out.println("Hello,you are welcom!");
            }
        }
) ;
    }
}

三、異常類

Java中本身也是包含有很多類的,具體的作用方法我一個菜鳥還是記不住的,就遇到了再記吧。那現在關於異常類中的方法,我還是查一下吧,簡單的...

異常類的祖先是Throwable,throwable的直接子類是 Exception 和 Error。

異常物件可以呼叫下列方法得到或輸出有關異常的資訊:

public String  getMessage();     //只顯示原因,不顯示類名

public void printStackTrace();   //跟蹤異常發生時堆疊的內容

public String toString();              //顯示類名和原因

Java允許方法呼叫過程中丟擲異常物件,終止當前方法的繼續執行。

1.try-catch語句

Java使用try-catch語句來處理異常,將可能出現的異常操作放在try-catch語句try部分,一旦try部分丟擲異常物件,或呼叫某個可能丟擲異常物件的方法,並且該方法丟擲了異常物件,(反正就是try語句裡有異常)那麼try部分立刻結束執行,轉向執行相應的catch部分。  故程式可以將發生異常後的處理放在catch部分,try-catch語句可以由幾個catch組成,分別處理髮生的相應異常。

其try-catch語句格式為:

try{

        包含可能發生異常的語句

}

catch(ExceptionSubClass1 e){     ......     }

catch(ExceptionSubClass2 e){     ......     }

各個catch引數中的異常類都是Exception的某個子類,表明try部分可能發生的異常,這些子類間不能有父子關係,否則保留一個含有父類引數的catch即可。

public class yichang {
	public static void main(String[] args) {
		int n =0 ,m = 0, t = 1000;
		try{
			m = Integer.parseInt("8888");
			n = Integer.parseInt("ab12");
			t = 999;
		}
		catch(NumberFormatException e){
			System.out.println("發生異常:" + e.getMessage());
		}
		System.out.println("n=" + n + ",m=" + m + ",t=" + t);
		try{
			System.out.println("故意丟擲I/O異常!");
			throw new java.io.IOException("我是故意的");
//			System.out.println("這個輸出語句是沒有機會被執行的");
		}
		catch(java.io.IOException e){
			System.out.println("發生異常:" + e.getMessage());
		}
	}
}

java.lang包中的 Integer 類呼叫其類方法public static int parseInt(String s)可以將 “數字”格式 的字串, 如“6789”, 轉化為 int型資料 ,但是當試圖將字串“ab89”轉換成數字時,例如:int number=Integer.parseInt(“ab89”);方法parseInt()在執行過程中就會丟擲 NumberFormatException 物件,即程式執行出現NumberFormatException異常(字串轉換成數字異常)。 

2.自定義異常類

可以自己編寫Exception的子類作為自己的異常類。使用 throws 關鍵字宣告要產生的異常(即在要判斷方法的方法名後面加throws  編寫的異常類類名),使用 throw 關鍵字丟擲該異常的物件,使該方法結束執行。

程式必須在try-catch塊語句中呼叫可能發生異常的方法,其中catch的作用就是捕獲throw關鍵字丟擲異常物件

//自定義的異常類,其實和普通的類一樣

public class BankException extends Exception{
    String message;
    public BankException(int m,int n) {
        message = "若入賬資金"+m+"是負數,或者支出"+n+"為正數,則錯誤"; 
    }
    public String warn(){
        return message;
    }
}

public class Bank {
    private int money;

//判斷方法中是否有異常
    public void income(int in,int out) throws BankException{  //宣告可能產生異常的類
        if(in<0||out>0||in+out<0){
            throw new BankException(in, out);   //若發生了異常對其進行丟擲
        }
        int netIncom = in +out;
        System.out.printf("本次純收入為:%d元\n",netIncom);
        money = money + netIncom;
    }
    public int getMoney(){
        return money;
    }
}

public class yichang {
    public static void main(String[] args) {
        Bank bank = new Bank();
        try{
            bank.income(200, -50);
            bank.income(300, -80);
            bank.income(500, -100);
            System.out.printf("銀行存款:%d元\n",bank.getMoney());
            bank.income(100, 50);  //  在這裡出現了異常,則立即結束執行
            bank.income(6000, -20);  //  不會被執行
        }
        catch(BankException e){
            System.out.println("發生問題為:");
            System.out.println(e.warn());
        }
        System.out.printf("銀行存款:%d元\n",bank.getMoney());
    }
}

3.finally語句

finally語句使用在try-catch語句後面的

try{.....}

catch(ExceptionSubClass e){.....}

finally{.....}

在執行了try-catch語句後,執行finally語句,也就是說,無論try部分是否發生異常,finally語句都會被執行。

But,若try-catch語句中執行了程式退出程式碼( 即執行System.exit(0);  ),則不會執行後面的所有語句(包括finally語句)。