溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Java的內(nèi)部類(lèi)和異常類(lèi)如何區(qū)分

發(fā)布時(shí)間:2022-02-23 14:58:40 來(lái)源:億速云 閱讀:116 作者:iii 欄目:開(kāi)發(fā)技術(shù)

本篇內(nèi)容主要講解“Java的內(nèi)部類(lèi)和異常類(lèi)如何區(qū)分”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Java的內(nèi)部類(lèi)和異常類(lèi)如何區(qū)分”吧!

    1 內(nèi)部類(lèi)

    Java支持在一個(gè)類(lèi)中聲明另一個(gè)類(lèi),這樣的類(lèi)稱(chēng)作內(nèi)部類(lèi),而包含內(nèi)部類(lèi)的類(lèi)成為內(nèi)部類(lèi)的外嵌類(lèi)。

    內(nèi)部類(lèi)的類(lèi)體中不可以聲明類(lèi)變量和類(lèi)方法。外嵌類(lèi)的類(lèi)體中可以用內(nèi)部類(lèi)聲明對(duì)象,作為外嵌類(lèi)的成員。

    內(nèi)部類(lèi)的使用規(guī)則:
    (1)聲明內(nèi)部類(lèi)如同在類(lèi)中聲明方法或變量一樣,一個(gè)類(lèi)把內(nèi)部類(lèi)看作是自己的成員。
    (2)外嵌類(lèi)的類(lèi)體中可以用內(nèi)部類(lèi)聲明的對(duì)象,作為外嵌類(lèi)的成員。
    (3)外嵌類(lèi)的成員變量在內(nèi)部類(lèi)中仍然有效,內(nèi)部類(lèi)中的方法也可以調(diào)用外嵌類(lèi)中的方法。
    (4)內(nèi)部類(lèi)的類(lèi)體中不可以聲明類(lèi)變量和方法。
    (5)外嵌類(lèi)和內(nèi)部類(lèi)在編譯時(shí),生成兩個(gè).class文件。

    例如:某種類(lèi)型的農(nóng)場(chǎng)飼養(yǎng)了一種特殊種類(lèi)的牛,但不希望其他農(nóng)場(chǎng)飼養(yǎng)這種特殊種類(lèi)的牛,那么這種類(lèi)型的農(nóng)場(chǎng)就可以將創(chuàng)建這種特殊種牛的類(lèi)作為自己的內(nèi)部類(lèi)。
    下面的例子1(Example1.1.java)中有一個(gè)RedCowForm(紅牛農(nóng)場(chǎng))類(lèi),該類(lèi)中有一個(gè)名字為RedCow (紅牛)的內(nèi)部類(lèi)。

    RedCowForm.java

    public class RedCowForm {
        static String formName;
        RedCow cow;  //內(nèi)部類(lèi)聲明對(duì)象
    
        RedCowForm() {
        }
    
        RedCowForm(String s) {
            cow = new RedCow(150, 112, 5000);
            formName = s;
        }
    
        public void showCowMess() {
            cow.speak();
        }
    
        class RedCow {  //內(nèi)部類(lèi)的聲明
            String cowName = "紅牛";
            int height, weight, price;
    
            RedCow(int h, int w, int p) {
                height = h;
                weight = w;
                price = p;
            }
    
            void speak() {
                System.out.println("偶是" + cowName + ",身高:" + height + "cm 體重:" + weight + "kg,生活在" + formName);
            }
        }    //內(nèi)部類(lèi)結(jié)束
    }
    115526523

    Example1.1.java

    public class Example1_1 {
        public static void main(String[] args) {
            RedCowForm form = new RedCowForm("紅牛農(nóng)場(chǎng)");
            form.showCowMess();
            form.cow.speak();
        }
    }

    需要特別注意的是,Java編譯器生成的內(nèi)部類(lèi)的字節(jié)碼文件的名字和通常的類(lèi)不同,內(nèi)部類(lèi)對(duì)應(yīng)的字節(jié)碼文件的名字格式是“外嵌類(lèi)名$ 內(nèi)部類(lèi)名”,例如,例子1中內(nèi)部類(lèi)的字節(jié)碼文件是RedCowForm$RedCow.class。因此,當(dāng)需要把字節(jié)碼文件復(fù)制給其他開(kāi)發(fā)人員時(shí),不要忘記了內(nèi)部類(lèi)的字節(jié)碼文件。
    內(nèi)部類(lèi)可以被修飾為static 內(nèi)部類(lèi),例如,例子1中的內(nèi)部類(lèi)聲明可以是static classRedCow。類(lèi)是一種數(shù)據(jù)類(lèi)型,那么static內(nèi)部類(lèi)就是外嵌類(lèi)中的一-種靜 態(tài)數(shù)據(jù)類(lèi)型,這樣一來(lái),程序就可以在其他類(lèi)中使用static內(nèi)部類(lèi)來(lái)創(chuàng)建對(duì)象了。但需要注意的是,static 內(nèi)部類(lèi)不能操作外嵌類(lèi)中的實(shí)例成員變量。

    假如將例子1中的內(nèi)部類(lèi)RedCow更改成static內(nèi)部類(lèi),就可以在例子1的Example1_ 1
    主類(lèi)的main方法中增加如下的代碼。

    RedCowForm.RedCow redCow = new RedCowForm.RedCow(180,119,6000);
            redCow.speak();

    注意:非內(nèi)部類(lèi)不可以是static類(lèi)

    2 匿名類(lèi)

    2.1 和子類(lèi)有關(guān)的匿名類(lèi)

    創(chuàng)建子類(lèi)對(duì)象時(shí),除了使用父類(lèi)的構(gòu)造方法外還有類(lèi)體,此類(lèi)體被認(rèn)為是一個(gè)子類(lèi)去掉類(lèi)聲明后的類(lèi)體,稱(chēng)作匿名類(lèi)。

    假設(shè)Bank是類(lèi),那么下列代碼就是用Bank的一個(gè)子類(lèi)(匿名類(lèi))創(chuàng)建對(duì)象:

    new Bank() {
    	匿名類(lèi)的類(lèi)體
    };

    和子類(lèi)有關(guān)的匿名類(lèi):
    (1)匿名類(lèi)是一個(gè)子類(lèi),由于無(wú)名可用,所以不可能用匿名類(lèi)聲明對(duì)象,但卻可以直接用匿名類(lèi)創(chuàng)建一個(gè)對(duì)象。
    (2)匿名類(lèi)可以繼承父類(lèi)的方法也可以重寫(xiě)父類(lèi)的方法。
    (3)使用匿名類(lèi)時(shí),必然是在某個(gè)類(lèi)中直接用匿名類(lèi)創(chuàng)建對(duì)象,以此,匿名類(lèi)一定是內(nèi)部類(lèi)。
    (4)匿名類(lèi)可以訪問(wèn)外嵌類(lèi)中的成員變量和方法,匿名類(lèi)的類(lèi)體中不可以聲明static成員變量和static方法。
    (5)由于匿名類(lèi)是一個(gè)子類(lèi),但沒(méi)有類(lèi)名,所以在用匿名類(lèi)創(chuàng)建對(duì)象時(shí),要直接使用父類(lèi)的構(gòu)造方法。

    例子2:該類(lèi)共有4個(gè)類(lèi): (Example2_1. java)、ShowBoard類(lèi)、
    OutputAlphabet類(lèi)型、 OutputEnglish. java 。該匿名類(lèi)的對(duì)象負(fù)責(zé)輸出希臘字母表。

    OutputAlphabet.java

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

    OutputAlphabet .java

    public class OutputEnglish extends OutputAlphabet { //輸出英文字母子類(lèi)
        public void output(){
            for (char c='a';c<='z';c++){
                System.out.printf("%3c",c);
            }
        }
    }

    ShowBoard .java

    public class ShowBoard {
        void showMess(OutputAlphabet show) { //參數(shù)show是OutputAlphabet類(lèi)型的對(duì)象
            show.output();
        }
    }

    Example2_1.java

    public class Example2_1 {
        public static void main(String[] args) {
            ShowBoard board = new ShowBoard();
            board.showMess(new OutputEnglish());//向參數(shù)傳遞OutputAlphabet的子類(lèi)OutputEnglish的對(duì)象
    
            board.showMess(new OutputAlphabet() {   //向參數(shù)傳遞OutputAlphabet的匿名子類(lèi)的對(duì)象
                @Override
                public void output() {
                    for (char c = 'α'; c <= 'ω'; c++)  //輸出希臘字母
                        System.out.printf("%3c", c);
                }
            });//分號(hào)在這里
        }
    }

    2.2 和接口有關(guān)的匿名類(lèi)

    和接口有關(guān)的匿名類(lèi)
    假設(shè)Computable是一個(gè)接口,那么,Java允許直接用接口名和一個(gè)類(lèi)體創(chuàng)建一個(gè)匿名對(duì)象,此類(lèi)體被認(rèn)為是實(shí)現(xiàn)了Computable接口的類(lèi)去掉類(lèi)聲明后的類(lèi)體,稱(chēng)作匿名類(lèi)。

    下列代碼就是用實(shí)現(xiàn)了Computable接口的類(lèi)(匿名類(lèi))創(chuàng)建對(duì)象:

    new Computable(){
    	實(shí)現(xiàn)接口的匿名類(lèi)的類(lèi)體
    };

    下面例子演示了和接口有關(guān)的匿名類(lèi)的用法:

    interface SpeakHello {
        void speak();
    }
    
    class HelloMachine {
        public void turnOn(SpeakHello hello) {
            hello.speak();
        }
    }
    
    public class Example7_3 {
        public static void main(String[] args) {
            HelloMachine machine = new HelloMachine();
            machine.turnOn(new SpeakHello() {
                @Override
                public void speak() {
                    System.out.println("hello,you are welcome!");
                }
            });
            machine.turnOn(new SpeakHello() {
                @Override
                public void speak() {
                    System.out.println("你好,歡迎光臨!");
                }
            });
        }
    }

    3 異常類(lèi)

    所謂異常就是程序運(yùn)行時(shí)可能出現(xiàn)一些錯(cuò)誤,比如試圖打開(kāi)一個(gè)根本不存在的文件等,異常處理將會(huì)改變程序的控制流程,讓程序有機(jī)會(huì)對(duì)錯(cuò)誤作出處理。程序運(yùn)行出現(xiàn)異常時(shí),Java運(yùn)行環(huán)境就用異常類(lèi)Exception的相應(yīng)子類(lèi)創(chuàng)建一個(gè)異常對(duì)象,并等待處理。異常對(duì)象可以調(diào)用如下方法得到或輸出有關(guān)異常的信息:

    異常對(duì)象可以調(diào)用如下方法得到或輸出有關(guān)異常的信息:

    public String getMessage();
    public void printStackTrace();
    public String toString();

    3.1 try-catch語(yǔ)句

    Java使用try-catch語(yǔ)句來(lái)處理異常,將可能出現(xiàn)的異常操作放在try-catch語(yǔ)句的try部分,將發(fā)生異常后的處理放在catch部分。
    try-catch語(yǔ)句的格式如下:

    try{
    	包含可能發(fā)生異常的語(yǔ)句
    }
    catch(ExceptionSubClass1 e){
    	...
    }
    catch(ExceptionSubClass2 e){
    	...
    }

    下面一個(gè)例子給出了try-catch語(yǔ)句的用法:

    public class Example3_1 {
        public static void main(String[] args) {
            int n = 0, m = 0, t = 1000;
    
            try {
                m = Integer.parseInt("8888");
                n = Integer.parseInt("ab89"); //發(fā)生異常,轉(zhuǎn)向catch
                t = 7777;  //t沒(méi)有機(jī)會(huì)被賦值
            } catch (NumberFormatException e) {
                System.out.println("發(fā)生異常:" + 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("這個(gè)輸出語(yǔ)句肯定沒(méi)有機(jī)會(huì)執(zhí)行,所以必須注釋掉,否則編譯出錯(cuò)");
            } catch (java.io.IOException e) {
                System.out.println("發(fā)生異常:" + e.getMessage());
            }
        }
    }

    帶finally子語(yǔ)句的try~catch語(yǔ)句,語(yǔ)法格式如下:

    try{ }
    catch(ExceptionSubClass e){ }
    finally{}

    其執(zhí)行機(jī)制是在執(zhí)行try~catch語(yǔ)句后,執(zhí)行finally 子語(yǔ)句,也就是說(shuō),無(wú)論在try部分是否發(fā)生過(guò)異常,finally 子語(yǔ)句都會(huì)被執(zhí)行

    3.2 自定義異常類(lèi)

    (1)一個(gè)方法不處理它產(chǎn)生的異常,而是沿著調(diào)用層次向上傳遞,由調(diào)用它的方法來(lái)處理這些異常,叫聲明異常.

    聲明異常的方法:
    在產(chǎn)生異常的方法名后面加上要拋出(throws)的異常的列表:

    如: void compute(int x) throwsAri thmeticException
    {//這里有異常發(fā)生,但是并沒(méi)有處理…}

    (2)我們也可以擴(kuò)展Exception類(lèi)定義自己的異常類(lèi),然后規(guī)定哪些方法產(chǎn)生這樣的異常。一個(gè)方法在聲明時(shí)可以使用throws關(guān)鍵字聲明要產(chǎn)生的若干個(gè)異常,并在該方法的方法體中具體給出產(chǎn)生異常的操
    作,即用相應(yīng)的異常類(lèi)創(chuàng)建對(duì)象,并使用throw關(guān)鍵字拋出該異常對(duì)象,導(dǎo)致該方法結(jié)束執(zhí)行。

    (3)通常情況下,計(jì)算兩個(gè)整數(shù)之和的方法不應(yīng)當(dāng)有任何異常放出,但是,對(duì)某些特殊應(yīng)程序,可能不允許同號(hào)的整數(shù)做求和運(yùn)算,比如當(dāng)一個(gè)整數(shù)代表收入,一個(gè)整數(shù)代表支出時(shí),這兩個(gè)整數(shù)就不能是同號(hào)。

    例子 (Example3_2. java)中,Bank類(lèi)中有一個(gè)income(int in, int out)方法,對(duì)象調(diào)用該方法時(shí),必須向參數(shù)in傳遞正整數(shù)、向參數(shù)out傳遞負(fù)數(shù),并且int+out必須大于等于0,否則該方法就拋出異常( BankException. java )。因此,Bank類(lèi)在聲明income(int in, int out)方法時(shí),使用throws關(guān)鍵字聲明要產(chǎn)生的異常。

    BankException.java

    public class BankException extends Exception {
        String message;
    
        public BankException(int m, int n) {
            message = "入賬資金" + m + "是負(fù)數(shù)或支出" + n + "是正數(shù),不符合系統(tǒng)要求.";
        }
    
        public String warnMess() {
            return message;
        }
    }

    Bank.java

    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); //方法拋出異常,導(dǎo)致方法結(jié)束
            }
            int netIncome = in + out;
            System.out.printf("本次計(jì)算出的純收入是:%d元
    ", netIncome);
            money = money + netIncome;
        }
    
        public int getMoney() {
            return money;
        }
    }

    Example3_2.java

    public class Example3_2 {
        public static void main(String[] args) {
            Bank bank = new Bank();
            try {
                bank.income(200, -100);
                bank.income(300, -100);
                bank.income(400, -100);
                System.out.printf("銀行目前有%d元
    ", bank.getMoney());
                bank.income(200, 100);
                bank.income(99999, -100);
            } catch (BankException e) {
                System.out.println("計(jì)算收益的過(guò)程出現(xiàn)如下問(wèn)題:");
                System.out.println(e.warnMess());
            }
            System.out.printf("銀行目前有%d元
    ", bank.getMoney());
        }
    }

    4 斷言

    斷言語(yǔ)句用于調(diào)試代碼階段。在調(diào)試代碼階段讓斷言語(yǔ)句發(fā)揮作用,這樣就可以發(fā)現(xiàn)一些致命的錯(cuò)誤,當(dāng)程序正式運(yùn)行時(shí)就可以關(guān)閉斷言語(yǔ)句,但仍把斷言語(yǔ)句保留在源代碼中,如果以后應(yīng)用程又需要調(diào)試,可以重新啟用斷言語(yǔ)句。

    使用關(guān)鍵字assert聲明一條斷言語(yǔ)句,斷言語(yǔ)句有以下兩種格式:

    assert booleanExpression;

    assert booleanExpression:messagelException;

    啟用與關(guān)閉斷言語(yǔ)句
    當(dāng)使用Java解釋器直接運(yùn)行應(yīng)用程序時(shí),默認(rèn)地關(guān)閉斷言語(yǔ)句,在調(diào)試程序時(shí)可以使用-ea啟用斷言語(yǔ)句,例如:
    java -ea mainClass

    例子4中,使用一個(gè)數(shù)組放著某學(xué)生5門(mén)課程的成績(jī),程序準(zhǔn)備計(jì)算學(xué)生的成績(jī)的總和。在調(diào)試程序時(shí)使用了斷言語(yǔ)句,如果發(fā)現(xiàn)成績(jī)有負(fù)數(shù),程序立刻結(jié)束執(zhí)行。程序調(diào)試開(kāi)啟斷言語(yǔ)句運(yùn)行效果如圖4.1,關(guān)閉斷言語(yǔ)句運(yùn)行效果如圖4.2。

    import java.util.Scanner;
    public class Example4 {
      public static void main (String args[ ]) {
           int [] score={-120,98,89,120,99};
           int sum=0;
           for(int number:score) {
              assert number>0:"負(fù)數(shù)不能是成績(jī)";
              sum=sum+number;
           } 
           System.out.println("總成績(jī):"+sum);    
       }
    }

    5 綜合案例

    下面的例子5中模擬向貨船上裝載集裝箱,如果貨船超重,那么貨船認(rèn)為這是一個(gè)異常將拒絕裝載集裝箱,但無(wú)論是否發(fā)生異常,貨船都需要正點(diǎn)啟航

    DangerException.java

    public class DangerException extends Exception {
        final String message = "超重";
        public String warnMess() {
            return message;
        }
    }

    CargoBoat.java

    public class CargoBoat {
        int realContent;  //裝載的重量
        int maxContent;   //最大裝載量
        public void setMaxContent(int c) {
            maxContent = c;
        }
        public void loading(int m) throws DangerException {
            realContent += m;
            if(realContent>maxContent) {
                throw new DangerException();
            }
            System.out.println("目前裝載了"+realContent+"噸貨物");
        }
    }

    Example5.java

    public class Example5 {
        public static void main(String[] args) {
            CargoBoat ship = new CargoBoat();
            ship.setMaxContent(1000);
            int m =600;
            try{
                ship.loading(m);
                m = 400;
                ship.loading(m);
                m = 367;
                ship.loading(m);
                m = 555;
                ship.loading(m);
            }
            catch(DangerException e) {
                System.out.println(e.warnMess());
                System.out.println("無(wú)法再裝載重量是"+m+"噸的集裝箱");
            }
            finally {
                System.out.printf("貨船將正點(diǎn)啟航");
            }
        }
    }

    到此,相信大家對(duì)“Java的內(nèi)部類(lèi)和異常類(lèi)如何區(qū)分”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢(xún),關(guān)注我們,繼續(xù)學(xué)習(xí)!

    向AI問(wèn)一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI