java基礎(chǔ)篇之異常D_第1頁
java基礎(chǔ)篇之異常D_第2頁
java基礎(chǔ)篇之異常D_第3頁
java基礎(chǔ)篇之異常D_第4頁
java基礎(chǔ)篇之異常D_第5頁
已閱讀5頁,還剩21頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、異常 異常的定義 在java編程思想中這樣定義 異常:阻止當(dāng)前方法或作用域繼續(xù)執(zhí)行的問題。雖然java中有異常處理機(jī)制,但是要明確一點(diǎn),決不應(yīng)該用"正常"的態(tài)度來看待異常。絕對(duì)一點(diǎn)說異常就是某種意義上的錯(cuò)誤,就是問題,它可能會(huì)導(dǎo)致程序失敗。之所以java要提出異常處理機(jī)制,就是要告訴開發(fā)人員,你的程序出現(xiàn)了不正常的情況,請(qǐng)注意。 記得當(dāng)初學(xué)習(xí)java的時(shí)候,異??偸歉悴惶宄恢肋@個(gè)異常是什么意思,為什么會(huì)有這個(gè)機(jī)制?但是隨著知識(shí)的積累逐漸也對(duì)異常有一點(diǎn)感覺了。 調(diào)用拋出異常的方法,必須處理異常,有兩種方式: 1、使用try catch finally 捕獲。 2、直接

2、再拋出異常。 注:處理異常的方式依賴于具體業(yè)務(wù)邏輯,可靈活處理。 如果代碼有異常發(fā)生,異常以后的代碼將不再執(zhí)行。 舉一個(gè)例子來說明一下異常的用途。public class Calculator public int devide(int num1, int num2) / 判斷除數(shù)是否為0if (num2 = 0) throw new IllegalArgumentException("除數(shù)不能為零");return num1 / num2; 看一下這個(gè)類中關(guān)于除運(yùn)算的方法,如果你是新手你可能會(huì)直接返回計(jì)算結(jié)果,根本不去考慮什么參數(shù)是否正確,是否合法(當(dāng)然可以原諒,誰都是這

3、樣過來的)。但是我們應(yīng)盡可能的考慮周全,把可能導(dǎo)致程序失敗的"苗頭"扼殺在搖籃中,所以進(jìn)行參數(shù)的合法性檢查就很有必要了。 其中執(zhí)行參數(shù)檢查拋出來的那個(gè)參數(shù)非法異常,這就屬于這個(gè)方法的不正常情況。正常情況下我們會(huì)正確的使用計(jì)算器,但是不排除粗心大意把除數(shù)賦值為0。 如果你之前沒有考慮到這種情況,并且恰巧用戶數(shù)學(xué)基礎(chǔ)不好,那么你完了。但是如果你之前考慮到了這種情況,那么很顯然錯(cuò)誤已在你的掌控之中。異常案例:public class User int id;String email;String pwd;public User() public User(int id, Stri

4、ng email, String pwd) super();this.id = id;this.email = email;this.pwd = pwd;Overridepublic String toString() return id + "," + email;Overridepublic boolean equals(Object obj) if (obj = null) return false;if (this = obj) return true;if (obj instanceof User) User o = (User) obj;return id =

5、o.id;return false;Overridepublic int hashCode() return id;-import java.util.HashMap;import java.util.Map;/* * 該類提供用戶管理功能:注冊(cè)和登錄 */public class UserManager / 存儲(chǔ)user對(duì)象的集合,key是email,value是用戶private Map<String, User> users = new HashMap<String, User>();private int id = 1;public User reg(Strin

6、g email, String pwd) throws UserExsitsException if (users.containsKey(email) throw new UserExsitsException("該郵箱" + email + "已存在!");User newuser = new User(id+, email, pwd);users.put(email, newuser);return newuser;public User login(String email, String pwd) throws EmailOrPwdExcept

7、ion if (!users.containsKey(email) throw new EmailOrPwdException("無此用戶!");User u = users.get(email);if (!u.pwd.equals(pwd) throw new EmailOrPwdException("密碼錯(cuò)誤!");return u;/* * 該類表示用戶已注冊(cè)過異常,一定繼承于excetpion類 * 用于表示注冊(cè)時(shí)可能已經(jīng)注冊(cè)過異常 */class UserExsitsException extends Exception public User

8、ExsitsException(String message) super(message);/* * 該類表示用戶名或密碼錯(cuò)誤異常,一定繼承于exception類 * 用于表示輸入的用戶名或密碼錯(cuò)誤異常 */class EmailOrPwdException extends Exception public EmailOrPwdException(String message) super(message);-public class ExceptionDemo public static void main(String args) throws Exception UserManager

9、 mgr = new UserManager();User u = mgr.reg("java_manual", "123abc");System.out.println("注冊(cè)成功!");/ 測(cè)試1,重復(fù)注冊(cè),出現(xiàn)異常u = mgr.reg("java_manual", "123abc");/ 測(cè)試2,登錄密碼錯(cuò)誤,出現(xiàn)異常,密碼不對(duì)u = mgr.login("java_manual", "abc");/ 測(cè)試3,登陸成功!User someone =

10、 mgr.login("java_manual", "123abc");System.out.println(someone);  注:        代碼調(diào)用拋出異常的方法,必須處理異常,有兩種方式:        1、使用try catch finally 捕獲。       

11、; 2、直接再拋出異常。        處理異常的方式依賴于具體業(yè)務(wù)邏輯,可靈活處理。     1) try 是嘗試運(yùn)程代碼塊,如果有異常會(huì)被隨后的catch捕獲,異常發(fā)生以后代碼不執(zhí)行。        2) catch代碼塊是異常處理代碼,需要提供合理的處理。       &#

12、160;1、異常的處理是不具體業(yè)務(wù)邏輯有關(guān)。        2、可以寫多個(gè)catch處理一系列異常,但是要注意:異常的大小關(guān)系,大類型的放到后面處理。        3) 有的時(shí)候直接catch(Exception) 粗粒度處理異常,代碼簡(jiǎn)潔,語義含糊. 根據(jù)業(yè)務(wù)邏輯適 當(dāng)選用。        4) fina

13、lly代碼塊,不管是否出現(xiàn)異常,總會(huì)執(zhí)行的代碼塊。        1、finally經(jīng)常用來處理現(xiàn)場(chǎng)的清理,比如:可靠的數(shù)據(jù)庫連接關(guān)閉。        5) 處理異常有一個(gè)基本原則:能夠底層處理的盡量處理,但是如果不能處理,必須拋出到調(diào)用者 (方法)。不應(yīng)該簡(jiǎn)單的拋棄。        6) 異常捕獲再拋出, 是一種把底

14、層異常迚行封裝,轉(zhuǎn)換為另外一種異常類型。        7) * 建議在捕獲到異常時(shí)候使用e.printStackTrace(),打印到控制臺(tái)。        1、輸出內(nèi)容是:出現(xiàn)異常時(shí)候的方法調(diào)用堆棧。        2、一般情況下,凡是捕獲異常代碼都輸出:e.printStackTrace()   

15、60;    【案例1】用戶登錄及異常處理_try catcvh捕捉異常        版本01        ExceptionDemo2.javapublic class ExceptionDemo2 public static void main(String args) UserManager mgr = new UserManager();try User u = mgr.re

16、g("java_manual", "123abc");System.out.println("注冊(cè)成功!");User someone = mgr.login("java_manual", "123abc");System.out.println(someone); catch (UserExsitsException e) e.printStackTrace(); catch (EmailOrPwdException e) e.printStackTrace();import java.uti

17、l.Scanner;public class ExceptionDemo3 public static void main(String args) UserManager mgr = new UserManager();Scanner s = new Scanner(System.in);while (true) System.out.println("1.注冊(cè) 2. 登錄");String cmd = s.nextLine();if ("1".equals(cmd) / 注冊(cè)用戶System.out.println("email:"

18、;);String email = s.nextLine();System.out.println("密碼:");String pwd = s.nextLine();try User u = mgr.reg(email, pwd);System.out.println("注冊(cè)成功:" + u); catch (UserExsitsException e) e.printStackTrace(); else if ("2".equals(cmd) / 用戶登錄System.out.println("email:");

19、String email = s.nextLine();System.out.println("密碼:");String pwd = s.nextLine();try User u = mgr.login(email, pwd);System.out.println("注冊(cè)成功:" + u); catch (EmailOrPwdException e) e.printStackTrace(); else System.out.println("不可識(shí)別的命令!");/* * 經(jīng)典筆試題目: 如下程序的執(zhí)行結(jié)果是什么? * A 0,0,

20、5 B 1,01 C 4,0,5 D 4,4,4 */public class TryCatchDemo public static void main(String args) System.out.println(test(null) + "," + test("0") + "," + test("");private static int test(String str) try return str.charAt(0) - '0' catch (NullPointerException e)

21、 e.printStackTrace();return 1; catch (RuntimeException e) e.printStackTrace();return 2; catch (Exception e) e.printStackTrace();return 3; finally return 4;/java.lang.NullPointerExceptionat basic.exception.TryCatchDemo.test(TryCatchDemo.java:14)at basic.exception.TryCatchDemo.main(TryCatchD

22、emo.java:9)java.lang.StringIndexOutOfBoundsException: String index out of range: 0at java.lang.String.charAt(Unknown Source)at basic.exception.TryCatchDemo.test(TryCatchDemo.java:14)at basic.exception.TryCatchDemo.main(TryCatchDemo.java:9)4,4,4 注: 1、

23、本案例在語法上允許(只是警告),但工作中丌會(huì)出現(xiàn),僅作為演示。 2、案例return 了2次(catch一次,finally一次)。 3、finally永遠(yuǎn)會(huì)被執(zhí)行。 4、捕獲(catch)異常有順序,異?!坝尚〉酱蟆?,否則會(huì)出編譯錯(cuò)誤。 5、NullPointerException 空指針異常。 6、StringIndexOutOfBoundsException 字符串下標(biāo)越界。異常分類:Throwable |-Error 是系統(tǒng)不可恢復(fù)的錯(cuò)誤,JVM發(fā)生的錯(cuò)誤 | |-OutOfMemoryError 堆內(nèi)存溢出 | |

24、-StackOverflowError 棧內(nèi)存溢出 |-Exception 程序可以檢查處理的異常,常見的異常繼承根 |-java.text.ParseException format 解析對(duì)象時(shí)候發(fā)生 | 如:Date d = dateformat.parse("2010-5-5"); |-RuntimeException 非檢查異常,Javac忽略對(duì)這類異常的語法檢查 |-IllegalArgumentException 

25、|-NullPointerException |-ArrayIndexOutOfBoundsException |-ClassCastException |-NumberFormatException * Integer.parseInt(S) 關(guān)于異常的分類: 1、Throwable 類是 Java 語言中所有錯(cuò)誤或異常的超類(這就是一切皆可拋的東西)。它有兩個(gè)子類:Error和Exception。 2、Error:用于指示合理的應(yīng)用程序不應(yīng)該試圖捕獲的嚴(yán)重問題。這種情況是很大的問題,大到你不能處理了,所以聽之任之就行了,你不用管它。比如說V

26、irtualMachineError:當(dāng)Java虛擬機(jī)崩潰或用盡了它繼續(xù)操作所需的資源時(shí),拋出該錯(cuò)誤。好吧,就算這個(gè)異常的存在了,那么應(yīng)該何時(shí),如何處理它呢?交給JVM吧,沒有比它更專業(yè)的了。 3、Exception:它指出了合理的應(yīng)用程序想要捕獲的條件。Exception又分為兩類:一種是CheckedException,一種是UncheckedException。這兩種Exception的區(qū)別主要是CheckedException需要用try.catch.顯示的捕獲,而UncheckedException不需要捕獲。通常UncheckedException又叫做RuntimeExcepti

27、on。effective java指出:對(duì)于可恢復(fù)的條件使用被檢查的異常(CheckedException),對(duì)于程序錯(cuò)誤(言外之意不可恢復(fù),大錯(cuò)已經(jīng)釀成)使用運(yùn)行時(shí)異常(RuntimeException)。 4、我們常見的RuntimeExcepiton有IllegalArgumentException、IllegalStateException、NullPointerException、IndexOutOfBoundsException等等。對(duì)于那些CheckedException就不勝枚舉了,我們?cè)诰帉懗绦蜻^程中try.catch.捕捉的異常都是CheckedException。io包中

28、的IOException及其子類,這些都是CheckedException。自定義異常: 軟件中會(huì)大量使用自定義異常,一般從Exception繼承異常類命名要有實(shí)際意義, 一般都手工繼承父類的構(gòu)造器。 使用Eclipse工具從父類創(chuàng)建構(gòu)造器/* 用戶注冊(cè)過的異常,一定要繼承于exception類 */public class UserExsitException extends Exception public UserExsitException() super();public UserExsitException(String message, Throwable cause) supe

29、r(message, cause);public UserExsitException(String message) super(message);異常的使用: 在異常的使用這一部分主要是演示代碼,都是我們平常寫代碼的過程中會(huì)遇到的(當(dāng)然只是一小部分),拋磚引玉嗎! 例1. 這個(gè)例子主要通過兩個(gè)方法對(duì)比來演示一下有了異常以后代碼的執(zhí)行流程。public static void testException1() int ints = new int 1, 2, 3, 4 ;System.out.println("異常出現(xiàn)前");try System.out.println(

30、ints4);System.out.println("我還有幸執(zhí)行到嗎");/ 發(fā)生異常以后,后面的代碼不能被執(zhí)行 catch (IndexOutOfBoundsException e) System.out.println("數(shù)組越界錯(cuò)誤");System.out.println("異常出現(xiàn)后");/* * output: 異常出現(xiàn)前 數(shù)組越界錯(cuò)誤 4 異常出現(xiàn)后 */public static void testException2() int ints = new int 1, 2, 3, 4 ;System.out.print

31、ln("異常出現(xiàn)前");System.out.println(ints4);System.out.println("我還有幸執(zhí)行到嗎");/ 發(fā)生異常以后,他后面的代碼不能被執(zhí)行 首先指出例子中的不足之處,IndexOutofBoundsException是一個(gè)非受檢異常,所以不用try.catch.顯示捕捉,但是我的目的是對(duì)同一個(gè)異常用不同的處理方式,看它會(huì)有什么不同的而結(jié)果(這里也就只能用它將就一下了)。異常出現(xiàn)時(shí)第一個(gè)方法只是跳出了try塊,但是它后面的代碼會(huì)照樣執(zhí)行的。但是第二種就不一樣了直接跳出了方法,比較強(qiáng)硬。從第一個(gè)方法中我們看到,try.

32、catch.是一種"事務(wù)性"的保障,它的目的是保證程序在異常的情況下運(yùn)行完畢,同時(shí)它還會(huì)告知程序員程序中出錯(cuò)的詳細(xì)信息(這種詳細(xì)信息有時(shí)要依賴于程序員設(shè)計(jì))。 例2. 重新拋出異常import java.io.BufferedInputStream;import java.io.FileInputStream;import java.io.FileNotFoundException;public class Rethrow public static void readFile(String file) throws FileNotFoundException try Bu

33、fferedInputStream in = new BufferedInputStream(new FileInputStream(file); catch (FileNotFoundException e) e.printStackTrace();System.err.println("不知道如何處理該異?;蛘吒静幌胩幚硭?,但是不做處理又不合適,這是重新拋出異常交給上一級(jí)處理");/ 重新拋出異常throw e;public static void printFile(String file) try readFile(file); catch (FileNotFou

34、ndException e) e.printStackTrace();public static void main(String args) printFile("D:/file"); 異常的本意是好的,讓我們?cè)噲D修復(fù)程序,但是現(xiàn)實(shí)中我們修復(fù)的幾率很小,我們很多時(shí)候就是用它來記錄出錯(cuò)的信息。如果你厭倦了不停的處理異常,重新拋出異常對(duì)你來說可能是一個(gè)很好的解脫。原封不動(dòng)的把這個(gè)異常拋給上一級(jí),拋給調(diào)用這個(gè)方法的人,讓他來費(fèi)腦筋吧。這樣看來,java異常(當(dāng)然指的是受檢異常)又給我們平添很多麻煩,盡管它的出發(fā)點(diǎn)是好的。 例3. 異常鏈的使用及異常丟失 定義三個(gè)異常類:Exce

35、ptionA,ExceptionB,ExceptionCpublic class ExceptionA extends Exception public ExceptionA(String str) super(); public class ExceptionB extends ExceptionA public ExceptionB(String str) super(str);public class ExceptionC extends ExceptionA public ExceptionC(String str) super(str); 異常丟失的情況:public class N

36、everCaught static void f() throws ExceptionB throw new ExceptionB("exception b");static void g() throws ExceptionC try f(); catch (ExceptionB e) ExceptionC c = new ExceptionC("exception a");throw c;public static void main(String args) try g(); catch (ExceptionC e) e.printStackTra

37、ce();/* * exception.ExceptionC at exception.NeverCaught.g(NeverCaught.java:12) at * exception.NeverCaught.main(NeverCaught.java:19) */ 為什么只是打印出來了ExceptionC而沒有打印出ExceptionB呢?這個(gè)還是自己分析一下吧! 上面的情況相當(dāng)于少了一種異常,這在我們排錯(cuò)的過程中非常的不利。那我們遇到上面的情況應(yīng)該怎么辦呢?這就是異常鏈的用武之地:保存異常信息,在拋出另外一個(gè)異常的同時(shí)不丟失原來的異常。public class NeverCaught2

38、static void f() throws ExceptionB throw new ExceptionB("exception b");static void g() throws ExceptionC try f(); catch (ExceptionB e) ExceptionC c = new ExceptionC("exception a");/ ?c.initCause(e);throw c;public static void main(String args) try g(); catch (ExceptionC e) e.printS

39、tackTrace();/* * exception.ExceptionC at exception.NeverCaught.g(NeverCaught.java:12) at * exception.NeverCaught.main(NeverCaught.java:21) Caused by: * exception.ExceptionB at exception.NeverCaught.f(NeverCaught.java:5) at * exception.NeverCaught.g(NeverCaught.java:10) . 1 more */ 這個(gè)異常鏈的特性是所有異常均具備的,

40、因?yàn)檫@個(gè)initCause()方法是從Throwable繼承的。 例4. 清理工作 清理工作對(duì)于我們來說是必不可少的,因?yàn)槿绻恍┫馁Y源的操作,比如IO,JDBC。如果我們用完以后沒有及時(shí)正確的關(guān)閉,那后果會(huì)很嚴(yán)重,這意味著內(nèi)存泄露。異常的出現(xiàn)要求我們必須設(shè)計(jì)一種機(jī)制不論什么情況下,資源都能及時(shí)正確的清理。這就是finally。public void readFile(String file) BufferedReader reader = null;try reader = new BufferedReader(new InputStreamReader(new FileInputStre

41、am(file);/ do some other work catch (FileNotFoundException e) e.printStackTrace(); finally try reader.close(); catch (IOException e) e.printStackTrace(); 例子非常的簡(jiǎn)單,是一個(gè)讀取文件的例子。這樣的例子在JDBC操作中也非常的常見。(所以,我覺得對(duì)于資源的及時(shí)正確清理是一個(gè)程序員的基本素質(zhì)之一。) Try.finally結(jié)構(gòu)也是保證資源正確關(guān)閉的一個(gè)手段。如果你不清楚代碼執(zhí)行過程中會(huì)發(fā)生什么異常情況會(huì)導(dǎo)致資源不能得到清理,那么你就用try對(duì)這

42、段"可疑"代碼進(jìn)行包裝,然后在finally中進(jìn)行資源的清理。舉一個(gè)例子:public void readFile() BufferedReader reader = null;try reader = new BufferedReader(new InputStreamReader(new FileInputStream("file");/ do some other work/ close readerreader.close(); catch (FileNotFoundException e) e.printStackTrace(); catch

43、(IOException e) e.printStackTrace(); 我們注意一下這個(gè)方法和上一個(gè)方法的區(qū)別,下一個(gè)人可能習(xí)慣更好一點(diǎn),及早的關(guān)閉reader。但是往往事與愿違,因?yàn)樵趓eader.close()以前異常隨時(shí)可能發(fā)生,這樣的代碼結(jié)構(gòu)不能預(yù)防任何異常的出現(xiàn)。因?yàn)槌绦驎?huì)在異常出現(xiàn)的地方跳出,后面的代碼不能執(zhí)行(這在上面應(yīng)經(jīng)用實(shí)例證明過)。這時(shí)我們就可以用try.finally來改造:public void readFile2() BufferedReader reader = null;try try reader = new BufferedReader(new InputS

44、treamReader(new FileInputStream("file");/ do some other work/ close reader finally reader.close(); catch (FileNotFoundException e) e.printStackTrace(); catch (IOException e) e.printStackTrace(); 及早的關(guān)閉資源是一種良好的行為,因?yàn)闀r(shí)間越長(zhǎng)你忘記關(guān)閉的可能性越大。這樣在配合上try.finally就保證萬無一失了(不要嫌麻煩,java就是這么中規(guī)中矩)。 再說一種情況,假如我想在構(gòu)造

45、方法中打開一個(gè)文件或者創(chuàng)建一個(gè)JDBC連接,因?yàn)槲覀円谄渌姆椒ㄖ惺褂眠@個(gè)資源,所以不能在構(gòu)造方法中及早的將這個(gè)資源關(guān)閉。那我們是不是就沒轍了呢?答案是否定的。 看一下下面的例子:mport java.io.BufferedReader;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStreamReader;public class ResourceInConstructor BufferedReader re

46、ader = null;public ResourceInConstructor() try reader = new BufferedReader(new InputStreamReader(new FileInputStream(""); catch (FileNotFoundException e) e.printStackTrace();public void readFile() try while (reader.readLine() != null) / do some work catch (IOException e) e.printStackTrace(

47、);public void dispose() try reader.close(); catch (IOException e) e.printStackTrace(); 這一部分講的多了一點(diǎn),但是異常確實(shí)是看起來容易用起來難的東西呀,java中還是有好多的東西需要深挖的。  對(duì)于異常的誤用著實(shí)很常見,上一部分中已經(jīng)列舉了幾個(gè),大家仔細(xì)的看一下。下面再說兩個(gè)其他的。        例1. 用一個(gè)Exception來捕捉所有的異常,頗有"一夫當(dāng)關(guān)萬夫莫開"的氣魄。不

48、過這也是最傻的行為。public void readFile3(String file) BufferedReader reader = null;Connection conn = null;try reader = new BufferedReader(new InputStreamReader(new FileInputStream(file);/ do some other workconn = DriverManager.getConnection("");/ . catch (Exception e) e.printStackTrace(); finally t

49、ry reader.close();conn.close(); catch (Exception e) e.printStackTrace(); 從異常角度來說這樣嚴(yán)格的程序確實(shí)是萬無一失,所有的異常都能捕獲。但是站在編程人員的角度,萬一這個(gè)程序出錯(cuò)了我們?cè)撊绾畏直媸堑降资悄且鸬哪兀琁O還是JDBC.所以,這種寫法很值得當(dāng)做一個(gè)反例。大家不要以為這種做法很幼稚,傻子才會(huì)做。我在公司實(shí)習(xí)時(shí)確實(shí)看見了類似的情況:只不過是人家沒有用Exception而是用了Throwable。 例2. 這里就不舉例子了,上面的程序都是反例。異常是程序處理意外情況的機(jī)制,當(dāng)程序發(fā)生意外時(shí),我們需要盡可能多的得到意外

50、的信息,包括發(fā)生的位置,描述,原因等等。這些都是我們解決問題的線索。但是上面的例子都只是簡(jiǎn)單的printStackTrace()。如果我們自己寫代碼,就要盡可能多的對(duì)這個(gè)異常進(jìn)行描述。比如說為什么會(huì)出現(xiàn)這個(gè)異常,什么情況下會(huì)發(fā)生這個(gè)異常。如果傳入方法的參數(shù)不正確,告知什么樣的參數(shù)是合法的參數(shù),或者給出一個(gè)sample。 例3. 將try block寫的簡(jiǎn)短,不要所有的東西都扔在這里,我們盡可能的分析出到底哪幾行程序可能出現(xiàn)異常,只是對(duì)可能出現(xiàn)異常的代碼進(jìn)行try。盡量為每一個(gè)異常寫一個(gè)try.catch,避免異常丟失。在IO操作中,一個(gè)IOException也具有"一夫當(dāng)關(guān)萬夫莫開&

51、quot;的氣魄。 反射 Java語言反射提供一種動(dòng)態(tài)鏈接程序組件的多功能方法。它允許程序創(chuàng)建和控制任何類的對(duì)象(根據(jù)安全性限制),無需提前硬編碼目標(biāo)類。這些特性使得反射特別適用于創(chuàng)建以非常普通的方式與對(duì)象協(xié)作的庫。例如,反射經(jīng)常在持續(xù)存儲(chǔ)對(duì)象為數(shù)據(jù)庫、XML或其它外部格式的框架中使用。Java reflection非常有用,它使類和數(shù)據(jù)結(jié)構(gòu)能按名稱動(dòng)態(tài)檢索相關(guān)信息,并允許在運(yùn)行著的程序中操作這些信息。 Java 的這一特性非常強(qiáng)大,并且是其它一些常用語言,如 C、C+、Fortran 或者 Pascal 等都不具備的。 但反射有兩個(gè)缺點(diǎn)。第一個(gè)是性能問題。用于字段和方法接入時(shí)反射要遠(yuǎn)慢于直接

52、代碼。性能問題的程度取決于程序中是如何使用反射的。如果它作為程序運(yùn)行中相對(duì)很少涉及的部分,緩慢的性能將不會(huì)是一個(gè)問題。即使測(cè)試中最壞情況下的計(jì)時(shí)圖顯示的反射操作只耗用幾微秒。僅反射在性能關(guān)鍵的應(yīng)用的核心邏輯中使用時(shí)性能問題才變得至關(guān)重要。 許多應(yīng)用中更嚴(yán)重的一個(gè)缺點(diǎn)是使用反射會(huì)模糊程序內(nèi)部實(shí)際要發(fā)生的事情。程序人員希望在源代碼中看到程序的邏輯,反射等繞過了源代碼的技術(shù)會(huì)帶來維護(hù)問題。反射代碼比相應(yīng)的直接代碼更復(fù)雜,正如性能比較的代碼實(shí)例中看到的一樣。解決這些問題的最佳方案是保守地使用反射僅在它可以真正增加靈活性的地方記錄其在目標(biāo)類中的使用。 Reflection是Java程序開發(fā)語言的特征之一

53、,它允許運(yùn)行中的Java程序?qū)ψ陨磉M(jìn)行檢查,或者說"自審",并能直接操作程序的內(nèi)部屬性。例如,使用它能獲得Java類中各成員的名稱并顯示出來。 Java的這一能力在實(shí)際應(yīng)用中也許用得不是很多,但是在其它的程序設(shè)計(jì)語言中根本就不存在這一特性。例如,Pascal、C或者C+中就沒有辦法在程序中獲得函數(shù)定義相關(guān)的信息。 JavaBean 是 reflection 的實(shí)際應(yīng)用之一,它能讓一些工具可視化的操作軟件組件。這些工具通過 reflection 動(dòng)態(tài)的載入并取得Java組件(類)的屬性。 在學(xué)習(xí)反射之前,讓我們先了解“類(Class)”?!胺椒ā?、“屬性”、“類”都是名詞,那

54、么相應(yīng)的在Java中會(huì)有這樣一些特殊的類:“方法類(Method類)”、“屬性類(Field類)”、“構(gòu)造器類(Constructor類)”、“類類(Class類)”。 如上所示,任何Java的類戒接口都是Class類的一個(gè)實(shí)例。 反射就是Java自我管理這些(類、對(duì)象)的機(jī)制。 1) 反射的作用(重點(diǎn)理解) 1、可以通過反射機(jī)制發(fā)現(xiàn)對(duì)象的類型,發(fā)現(xiàn)類型的方法/屬性/構(gòu)造器。 2、可以創(chuàng)建對(duì)象并訪問任意對(duì)象方法和屬性等。 2) Class加載 類加載到內(nèi)存:Java將磁盤類文件加載到內(nèi)存中,為一個(gè)對(duì)象(實(shí)例),這個(gè)對(duì)象是Class的實(shí)例。 3) Class實(shí)例代表Java中類型 獲得基本類型實(shí)

55、例int.classlong.class.Class cls = "abc".getClass();獲得類類型(Class)實(shí)例:Class cls = String.class; Class cls = Class.forName("java.lang.String"); Class cls = "abc".getClass();以上方法獲得的cls是同一個(gè)對(duì)象, 就是String&#

56、160;類內(nèi)存加載的結(jié)果。 考慮下面這個(gè)簡(jiǎn)單的例子,讓我們看看 reflection 是如何工作的。import java.lang.reflect.*;public class DumpMethods public static void main(String args) try Class c = Class.forName(args0);Method m = c.getDeclaredMethods();for (int i = 0; i < m.length; i+)System.out.println(mi.toString(); catch (Throwable e) System.err.println(e); 按如下語句執(zhí)行:java Du

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論