Java內(nèi)部類和異常類的概念以及使用
1 內(nèi)部類
Java支持在一個(gè)類中聲明另一個(gè)類,這樣的類稱作內(nèi)部類,而包含內(nèi)部類的類成為內(nèi)部類的外嵌類。
內(nèi)部類的類體中不可以聲明類變量和類方法。外嵌類的類體中可以用內(nèi)部類聲明對象,作為外嵌類的成員。
內(nèi)部類的使用規(guī)則:
(1)聲明內(nèi)部類如同在類中聲明方法或變量一樣,一個(gè)類把內(nèi)部類看作是自己的成員。
(2)外嵌類的類體中可以用內(nèi)部類聲明的對象,作為外嵌類的成員。
(3)外嵌類的成員變量在內(nèi)部類中仍然有效,內(nèi)部類中的方法也可以調(diào)用外嵌類中的方法。
(4)內(nèi)部類的類體中不可以聲明類變量和方法。
(5)外嵌類和內(nèi)部類在編譯時(shí),生成兩個(gè).class文件。
例如:某種類型的農(nóng)場飼養(yǎng)了一種特殊種類的牛,但不希望其他農(nóng)場飼養(yǎng)這種特殊種類的牛,那么這種類型的農(nóng)場就可以將創(chuàng)建這種特殊種牛的類作為自己的內(nèi)部類。
下面的例子1(Example1.1.java)中有一個(gè)RedCowForm(紅牛農(nóng)場)類,該類中有一個(gè)名字為RedCow (紅牛)的內(nèi)部類。
RedCowForm.java
public class RedCowForm { static String formName; RedCow cow; //內(nèi)部類聲明對象 RedCowForm() { } RedCowForm(String s) { cow = new RedCow(150, 112, 5000); formName = s; } public void showCowMess() { cow.speak(); } class RedCow { //內(nè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)部類結(jié)束 } 115526523
Example1.1.java
public class Example1_1 { public static void main(String[] args) { RedCowForm form = new RedCowForm("紅牛農(nóng)場"); form.showCowMess(); form.cow.speak(); } }
需要特別注意的是,Java編譯器生成的內(nèi)部類的字節(jié)碼文件的名字和通常的類不同,內(nèi)部類對應(yīng)的字節(jié)碼文件的名字格式是“外嵌類名$ 內(nèi)部類名”,例如,例子1中內(nèi)部類的字節(jié)碼文件是RedCowForm$RedCow.class。因此,當(dāng)需要把字節(jié)碼文件復(fù)制給其他開發(fā)人員時(shí),不要忘記了內(nèi)部類的字節(jié)碼文件。
內(nèi)部類可以被修飾為static 內(nèi)部類,例如,例子1中的內(nèi)部類聲明可以是static classRedCow。類是一種數(shù)據(jù)類型,那么static內(nèi)部類就是外嵌類中的一-種靜 態(tài)數(shù)據(jù)類型,這樣一來,程序就可以在其他類中使用static內(nèi)部類來創(chuàng)建對象了。但需要注意的是,static 內(nèi)部類不能操作外嵌類中的實(shí)例成員變量。
假如將例子1中的內(nèi)部類RedCow更改成static內(nèi)部類,就可以在例子1的Example1_ 1
主類的main方法中增加如下的代碼。
RedCowForm.RedCow redCow = new RedCowForm.RedCow(180,119,6000); redCow.speak();
注意:非內(nèi)部類不可以是static類
2 匿名類
2.1 和子類有關(guān)的匿名類
創(chuàng)建子類對象時(shí),除了使用父類的構(gòu)造方法外還有類體,此類體被認(rèn)為是一個(gè)子類去掉類聲明后的類體,稱作匿名類。
假設(shè)Bank是類,那么下列代碼就是用Bank的一個(gè)子類(匿名類)創(chuàng)建對象:
new Bank() { 匿名類的類體 };
和子類有關(guān)的匿名類:
(1)匿名類是一個(gè)子類,由于無名可用,所以不可能用匿名類聲明對象,但卻可以直接用匿名類創(chuàng)建一個(gè)對象。
(2)匿名類可以繼承父類的方法也可以重寫父類的方法。
(3)使用匿名類時(shí),必然是在某個(gè)類中直接用匿名類創(chuàng)建對象,以此,匿名類一定是內(nèi)部類。
(4)匿名類可以訪問外嵌類中的成員變量和方法,匿名類的類體中不可以聲明static成員變量和static方法。
(5)由于匿名類是一個(gè)子類,但沒有類名,所以在用匿名類創(chuàng)建對象時(shí),要直接使用父類的構(gòu)造方法。
例子2:該類共有4個(gè)類: (Example2_1. java)、ShowBoard類、
OutputAlphabet類型、 OutputEnglish. java 。該匿名類的對象負(fù)責(zé)輸出希臘字母表。
OutputAlphabet.java
abstract class OutputAlphabet { public abstract void output(); }
OutputAlphabet .java
public class OutputEnglish extends OutputAlphabet { //輸出英文字母子類 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類型的對象 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的子類OutputEnglish的對象 board.showMess(new OutputAlphabet() { //向參數(shù)傳遞OutputAlphabet的匿名子類的對象 @Override public void output() { for (char c = 'α'; c <= 'ω'; c++) //輸出希臘字母 System.out.printf("%3c", c); } });//分號(hào)在這里 } }
2.2 和接口有關(guān)的匿名類
和接口有關(guān)的匿名類
假設(shè)Computable是一個(gè)接口,那么,Java允許直接用接口名和一個(gè)類體創(chuàng)建一個(gè)匿名對象,此類體被認(rèn)為是實(shí)現(xiàn)了Computable接口的類去掉類聲明后的類體,稱作匿名類。
下列代碼就是用實(shí)現(xiàn)了Computable接口的類(匿名類)創(chuàng)建對象:
new Computable(){ 實(shí)現(xiàn)接口的匿名類的類體 };
下面例子演示了和接口有關(guān)的匿名類的用法:
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 異常類
所謂異常就是程序運(yùn)行時(shí)可能出現(xiàn)一些錯(cuò)誤,比如試圖打開一個(gè)根本不存在的文件等,異常處理將會(huì)改變程序的控制流程,讓程序有機(jī)會(huì)對錯(cuò)誤作出處理。程序運(yùn)行出現(xiàn)異常時(shí),Java運(yùn)行環(huán)境就用異常類Exception的相應(yīng)子類創(chuàng)建一個(gè)異常對象,并等待處理。異常對象可以調(diào)用如下方法得到或輸出有關(guān)異常的信息:
異常對象可以調(diào)用如下方法得到或輸出有關(guān)異常的信息:
public String getMessage(); public void printStackTrace(); public String toString();
3.1 try-catch語句
Java使用try-catch語句來處理異常,將可能出現(xiàn)的異常操作放在try-catch語句的try部分,將發(fā)生異常后的處理放在catch部分。
try-catch語句的格式如下:
try{ 包含可能發(fā)生異常的語句 } catch(ExceptionSubClass1 e){ ... } catch(ExceptionSubClass2 e){ ... }
下面一個(gè)例子給出了try-catch語句的用法:
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沒有機(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è)輸出語句肯定沒有機(jī)會(huì)執(zhí)行,所以必須注釋掉,否則編譯出錯(cuò)"); } catch (java.io.IOException e) { System.out.println("發(fā)生異常:" + e.getMessage()); } } }
帶finally子語句的try~catch語句,語法格式如下:
try{ } catch(ExceptionSubClass e){ } finally{}
其執(zhí)行機(jī)制是在執(zhí)行try~catch語句后,執(zhí)行finally 子語句,也就是說,無論在try部分是否發(fā)生過異常,finally 子語句都會(huì)被執(zhí)行
3.2 自定義異常類
(1)一個(gè)方法不處理它產(chǎn)生的異常,而是沿著調(diào)用層次向上傳遞,由調(diào)用它的方法來處理這些異常,叫聲明異常.
聲明異常的方法:
在產(chǎn)生異常的方法名后面加上要拋出(throws)的異常的列表:
如: void compute(int x) throwsAri thmeticException
{//這里有異常發(fā)生,但是并沒有處理…}
(2)我們也可以擴(kuò)展Exception類定義自己的異常類,然后規(guī)定哪些方法產(chǎn)生這樣的異常。一個(gè)方法在聲明時(shí)可以使用throws關(guān)鍵字聲明要產(chǎn)生的若干個(gè)異常,并在該方法的方法體中具體給出產(chǎn)生異常的操
作,即用相應(yīng)的異常類創(chuàng)建對象,并使用throw關(guān)鍵字拋出該異常對象,導(dǎo)致該方法結(jié)束執(zhí)行。
(3)通常情況下,計(jì)算兩個(gè)整數(shù)之和的方法不應(yīng)當(dāng)有任何異常放出,但是,對某些特殊應(yīng)程序,可能不允許同號(hào)的整數(shù)做求和運(yùn)算,比如當(dāng)一個(gè)整數(shù)代表收入,一個(gè)整數(shù)代表支出時(shí),這兩個(gè)整數(shù)就不能是同號(hào)。
例子 (Example3_2. java)中,Bank類中有一個(gè)income(int in, int out)方法,對象調(diào)用該方法時(shí),必須向參數(shù)in傳遞正整數(shù)、向參數(shù)out傳遞負(fù)數(shù),并且int+out必須大于等于0,否則該方法就拋出異常( BankException. java )。因此,Bank類在聲明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元\n", 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元\n", bank.getMoney()); bank.income(200, 100); bank.income(99999, -100); } catch (BankException e) { System.out.println("計(jì)算收益的過程出現(xiàn)如下問題:"); System.out.println(e.warnMess()); } System.out.printf("銀行目前有%d元\n", bank.getMoney()); } }
4 斷言
斷言語句用于調(diào)試代碼階段。在調(diào)試代碼階段讓斷言語句發(fā)揮作用,這樣就可以發(fā)現(xiàn)一些致命的錯(cuò)誤,當(dāng)程序正式運(yùn)行時(shí)就可以關(guān)閉斷言語句,但仍把斷言語句保留在源代碼中,如果以后應(yīng)用程又需要調(diào)試,可以重新啟用斷言語句。
使用關(guān)鍵字assert聲明一條斷言語句,斷言語句有以下兩種格式:
assert booleanExpression;
assert booleanExpression:messagelException;
啟用與關(guān)閉斷言語句
當(dāng)使用Java解釋器直接運(yùn)行應(yīng)用程序時(shí),默認(rèn)地關(guān)閉斷言語句,在調(diào)試程序時(shí)可以使用-ea啟用斷言語句,例如:
java -ea mainClass
例子4中,使用一個(gè)數(shù)組放著某學(xué)生5門課程的成績,程序準(zhǔn)備計(jì)算學(xué)生的成績的總和。在調(diào)試程序時(shí)使用了斷言語句,如果發(fā)現(xiàn)成績有負(fù)數(shù),程序立刻結(jié)束執(zhí)行。程序調(diào)試開啟斷言語句運(yùn)行效果如圖4.1,關(guān)閉斷言語句運(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ù)不能是成績"; sum=sum+number; } System.out.println("總成績:"+sum); } }
圖4.1
圖4.2
5 綜合案例
下面的例子5中模擬向貨船上裝載集裝箱,如果貨船超重,那么貨船認(rèn)為這是一個(gè)異常將拒絕裝載集裝箱,但無論是否發(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("無法再裝載重量是"+m+"噸的集裝箱"); } finally { System.out.printf("貨船將正點(diǎn)啟航"); } } }
到此這篇關(guān)于Java內(nèi)部類和異常類的概念以及使用的文章就介紹到這了,更多相關(guān)java類的使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解java 三種調(diào)用機(jī)制(同步、回調(diào)、異步)
這篇文章主要介紹了java 三種調(diào)用機(jī)制(同步、回調(diào)、異步),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04Vue中computed計(jì)算屬性和data數(shù)據(jù)獲取方式
這篇文章主要介紹了Vue中computed計(jì)算屬性和data數(shù)據(jù)獲取方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03Java開發(fā)學(xué)習(xí)之Bean的作用域和生命周期詳解
這篇文章主要介紹了淺談Spring中Bean的作用域,生命周期和注解,從創(chuàng)建到消亡的完整過程,例如人從出生到死亡的整個(gè)過程就是一個(gè)生命周期。本文將通過示例為大家詳細(xì)講講,感興趣的可以學(xué)習(xí)一下2022-06-06SpringBoot項(xiàng)目導(dǎo)出jar包及瘦身部署方式
今天項(xiàng)目要求Nginx+jar包運(yùn)行多個(gè)項(xiàng)目,在此記錄一下部署的過程,其中借鑒了好多網(wǎng)上前輩的經(jīng)驗(yàn),感謝各位的無私分享2024-07-07完整java開發(fā)中JDBC連接數(shù)據(jù)庫代碼和步驟
這篇文章主要介紹了完整java開發(fā)中JDBC連接數(shù)據(jù)庫代碼和步驟,需要的朋友可以參考下2015-09-09SpringCloud微服務(wù)架構(gòu)實(shí)戰(zhàn)之微服務(wù)治理功能的實(shí)現(xiàn)
這篇文章主要介紹了SpringCloud微服務(wù)架構(gòu)實(shí)戰(zhàn)之微服務(wù)治理,這些治理工具主要包括服務(wù)的注冊與發(fā)現(xiàn)、負(fù)載均衡管理、動(dòng)態(tài)路由、服務(wù)降級(jí)和故障轉(zhuǎn)移、鏈路跟蹤、服務(wù)監(jiān)控等,需要的朋友可以參考下2022-02-02AgileBoot?項(xiàng)目內(nèi)統(tǒng)一的錯(cuò)誤碼設(shè)計(jì)分析
這篇文章主要為大家介紹了AgileBoot?項(xiàng)目內(nèi)統(tǒng)一的錯(cuò)誤碼設(shè)計(jì)分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10