導航:首頁 > 編程語言 > java的handler機制

java的handler機制

發布時間:2022-08-07 16:11:35

java動態代理機制

在目前的Java開發包中包含了對動態代理的支持,但是其實現只支持對介面的的實現。

其實現主要通過是java.lang.reflect.Proxy類和java.lang.reflect.InvocationHandler介面。

Proxy類主要用來獲取動態代理對象,InvocationHandler介面用來約束調用者實現,如下,HelloWorld介面定義的業務方法,HelloWorldImpl是HelloWorld介面的實現,HelloWorldHandler是 InvocationHandler介面實現。代碼如下:

業務介面:

public interface HelloWorld {
void sayHelloWorld() ;

}

業務介面實現:

public class HelloWorldImpl implements HelloWorld {
public void sayHelloWorld() {

System.out.println("Hello World!");

}

}

InvocationHandler實現,需要在介面方法調用前後加入一部份處理工作,這里僅僅在方法調用前後向後台輸出兩句字元串,其代碼如下:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class HelloWorldHandler implements InvocationHandler {

//要代理的原始對象

private Object objOriginal;

/**

* 構造函數。

* @param obj 要代理的原始對象。

*/

public HelloWorldHandler(Object obj) {

this.objOriginal = obj ;

}

public Object invoke(Object proxy, Method method, Object[] args)

throws Throwable {

Object result ;

//方法調用之前

doBefore();

//調用原始對象的方法

result = method.invoke(this.objOriginal ,args);

//方法調用之後

doAfter();

return result ;

}

private void doBefore() {

System.out.println("before method invoke!");

}

private void doAfter() {

System.out.println("after method invoke!");

}

}

測試代碼:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class Test {

public static void main(String[] args) {

HelloWorld hw = new HelloWorldImpl();

InvocationHandler handler = new HelloWorldHandler(hw);

HelloWorld proxy = (HelloWorld) Proxy.newProxyInstance(

hw.getClass().getClassLoader(),

hw.getClass().getInterfaces(),

handler);

proxy.sayHelloWorld();

}

}

Ø 首先獲取一個業務介面的實現對象;

Ø 獲取一個InvocationHandler實現,此處是HelloWorldHandler對象;

Ø 創建動態代理對象;

Ø 通過動態代理對象調用sayHelloWorld()方法,此時會在原始對象HelloWorldImpl. sayHelloWorld()方法前後輸出兩句字元串。

運行測試類輸出如下:

before method invoke!

Hello World!

after method invoke!

此處Test類中的方法調用代碼比較多,在我們的實際應用中可以通過配置文件來來簡化客戶端的調用實現。另外也可以通過動態代理來實現簡單的AOP。

② handler怎麼解決多線程並發

我們知道Spring通過各種DAO模板類降低了開發者使用各種數據持久技術的難度。這些模板類都是線程安全的,也就是說,多個DAO可以復用同一個模板實例而不會發生沖突。我們使用模板類訪問底層數據,根據持久化技術的不同,模板類需要綁定數據連接或會話的資源。但這些資源本身是非線程安全的,也就是說它們不能在同一時刻被多個線程共享。雖然模板類通過資源池獲取數據連接或會話,但資源池本身解決的是數據連接或會話的緩存問題,並非數據連接或會話的線程安全問題。按照傳統經驗,如果某個對象是非線程安全的,在多線程環境下,對對象的訪問必須採用synchronized進行線程同步。但Spring的DAO模板類並未採用線程同步機制,因為線程同步限制了並發訪問,會帶來很大的性能損失。此外,通過代碼同步解決性能安全問題挑戰性很大,可能會增強好幾倍的實現難度。那模板類究竟仰丈何種魔法神功,可以在無需同步的情況下就化解線程安全的難題呢?答案就是ThreadLocal!ThreadLocal在Spring中發揮著重要的作用,在管理request作用域的Bean、事務管理、任務調度、AOP等模塊都出現了它們的身影,起著舉足輕重的作用。要想了解Spring事務管理的底層技術,ThreadLocal是必須攻克的山頭堡壘。ThreadLocal是什麼早在JDK1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal為解決多線程程序的並發問題提供了一種新的思路。使用這個工具類可以很簡潔地編寫出優美的多線程程序。ThreadLocal很容易讓人望文生義,想當然地認為是一個「本地線程」。其實,ThreadLocal並不是一個Thread,而是Thread的局部變數,也許把它命名為ThreadLocalVariable更容易讓人理解一些。當使用ThreadLocal維護變數時,ThreadLocal為每個使用該變數的線程提供獨立的變數副本,所以每一個線程都可以獨立地改變自己的副本,而不會影響其它線程所對應的副本。從線程的角度看,目標變數就象是線程的本地變數,這也是類名中「Local」所要表達的意思。線程局部變數並不是Java的新發明,很多語言(如IBMIBMXLFORTRAN)在語法層面就提供線程局部變數。在Java中沒有提供在語言級支持,而是變相地通過ThreadLocal的類提供支持。所以,在Java中編寫線程局部變數的代碼相對來說要笨拙一些,因此造成線程局部變數沒有在Java開發者中得到很好的普及。ThreadLocal的介面方法ThreadLocal類介面很簡單,只有4個方法,我們先來了解一下:voidset(Objectvalue)設置當前線程的線程局部變數的值。publicObjectget()該方法返回當前線程所對應的線程局部變數。publicvoidremove()將當前線程局部變數的值刪除,目的是為了減少內存的佔用,該方法是JDK5.0新增的方法。需要指出的是,當線程結束後,對應該線程的局部變數將自動被垃圾回收,所以顯式調用該方法清除線程的局部變數並不是必須的操作,但它可以加快內存回收的速度。protectedObjectinitialValue()返回該線程局部變數的初始值,該方法是一個protected的方法,顯然是為了讓子類覆蓋而設計的。這個方法是一個延遲調用方法,在線程第1次調用get()或set(Object)時才執行,並且僅執行1次。ThreadLocal中的預設實現直接返回一個null。值得一提的是,在JDK5.0中,ThreadLocal已經支持泛型,該類的類名已經變為ThreadLocal。API方法也相應進行了調整,新版本的API方法分別是voidset(Tvalue)、Tget()以及TinitialValue()。ThreadLocal是如何做到為每一個線程維護變數的副本的呢?其實實現的思路很簡單:在ThreadLocal類中有一個Map,用於存儲每一個線程的變數副本,Map中元素的鍵為線程對象,而值對應線程的變數副本。我們自己就可以提供一個簡單的實現版本://代碼清單{privateMapvalueMap=Collections.synchronizedMap(newHashMap());publicvoidset(ObjectnewValue){valueMap.put(Thread.currentThread(),newValue);//①鍵為線程對象,值為本線程的變數副本}publicObjectget(){ThreadcurrentThread=Thread.currentThread();Objecto=valueMap.get(currentThread);//②返回本線程對應的變數if(o==null&&!valueMap.containsKey(currentThread)){//③如果在Map中不存在,放到Map//中保存起來。o=initialValue();valueMap.put(currentThread,o);}returno;}publicvoidremove(){valueMap.remove(Thread.currentThread());}publicObjectinitialValue(){returnnull;}}雖然代碼清單9?3這個ThreadLocal實現版本顯得比較幼稚,但它和JDK所提供的ThreadLocal類在實現思路上是相近的。一個TheadLocal實例下面,我們通過一個具體的實例了解一下ThreadLocal的具體使用方法packagethreadLocalDemo;publicclassSequenceNumber{//①通過匿名內部類覆蓋ThreadLocal的initialValue()方法,指定初始值=newThreadLocal(){publicIntegerinitialValue(){return0;}};//②獲取下一個序列值publicintgetNextNum(){seqNum.set(seqNum.get()+1);returnseqNum.get();}publicstaticvoidmain(String[]args){SequenceNumbersn=newSequenceNumber();//③3個線程共享sn,各自產生序列號TestClientt1=newTestClient(sn);TestClientt2=newTestClient(sn);TestClientt3=newTestClient(sn);t1.start();t2.start();t3.start();}{privateSequenceNumbersn;publicTestClient(SequenceNumbersn){this.sn=sn;}publicvoidrun(){for(inti=0;i版本。概括起來說,對於多線程資源共享的問題,同步機制採用了「以時間換空間」的方式,而ThreadLocal採用了「以空間換時間」的方式。前者僅提供一份變數,讓不同的線程排隊訪問,而後者為每一個線程都提供了一份變數,因此可以同時訪問而互不影響。Spring使用ThreadLocal解決線程安全問題我們知道在一般情況下,只有無狀態的Bean才可以在多線程環境下共享,在Spring中,絕大部分Bean都可以聲明為singleton作用域。就是因為Spring對一些Bean(如RequestContextHolder、、LocaleContextHolder等)中非線程安全狀態採用ThreadLocal進行處理,讓它們也成為線程安全的狀態,因為有狀態的Bean就可以在多線程中共享了。一般的Web應用劃分為展現層、服務層和持久層三個層次,在不同的層中編寫對應的邏輯,下層通過介面向上層開放功能調用。在一般情況下,從接收請求到返回響應所經過的所有程序調用都同屬於一個線程,如圖9?2所示:圖1同一線程貫通三層這樣你就可以根據需要,將一些非線程安全的變數以ThreadLocal存放,在同一次請求響應的調用線程中,所有關聯的對象引用到的都是同一個變數。下面的實例能夠體現Spring對有狀態Bean的改造思路:代碼清單3TopicDao:非線程安全publicclassTopicDao{privateConnectionconn;①一個非線程安全的變數publicvoidaddTopic(){Statementstat=conn.createStatement();②引用非線程安全變數…}}由於①處的conn是成員變數,因為addTopic()方法是非線程安全的,必須在使用時創建一個新TopicDao實例(非singleton)。下面使用ThreadLocal對conn這個非線程安全的「狀態」進行改造:代碼清單4TopicDao:線程安全packagethreadLocalDemo;importjava.sql.Connection;importjava.sql.SQLException;importjava.sql.Statement;publicclassSqlConnection{//①使用ThreadLocal保存Connection變數=newThreadLocal();(){//②如果connThreadLocal沒有本線程對應的Connection創建一個新的Connection,//並將其保存到線程本地變數中。if(connThreadLocal.get()==null){Connectionconn=getConnection();connThreadLocal.set(conn);returnconn;}else{returnconnThreadLocal.get();//③直接返回線程本地變數}}publicvoidaddTopic(){//④從ThreadLocal中獲取線程對應的Connectiontry{Statementstat=getConnection().createStatement();}catch(SQLExceptione){e.printStackTrace();}}}

③ java中有沒有signal機制

java中提供了signal的機制。在sun.misc包下,屬於非標准包。重要涉及到兩個類:Signal和SignalHandler。其中Signal主要使用了靜態方法Signal.handle(Signal, SignalHandler),而SignalHandler是一個介面。

提供如下示例代碼:
public static void main(String[] args) throws InterruptedException {
SignalHandler signalHandler = new SignalHandler() {
@Override
public void handle(Signal signal) {
System.out.println("SignalHandler: " + signal);
}
};
// 只有kill -9能夠結束jvm進程,別的信號量只是發送給java進程處理,至於如何響應是程序代碼決定的
Signal.handle(new Signal("HUP"), signalHandler); // kill -1 PID
Signal.handle(new Signal("INT"), signalHandler); // kill -2 PID
// already used by VM or OS: SIGQUIT
// Signal.handle(new Signal("QUIT"), signalHandler); // kill -3 PID
Signal.handle(new Signal("ABRT"), signalHandler); // kill -6 PID
// already used by VM or OS: SIGKILL
// Signal.handle(new Signal("KILL"), signalHandler); // kill -9 PID
Signal.handle(new Signal("ALRM"), signalHandler); // kill -14 PID
Signal.handle(new Signal("TERM"), signalHandler); // kill -15 PID

for (int i = 0; i < 100; i++) {
Thread.sleep(1000);
System.out.println(i);
}
}

④ java中 方法中拋出異常處理方法

Java語言提供兩種異常處理機制:捕獲異常和聲明拋棄異常。

1、捕獲異常:

(1)在Java程序運行過程中系統得到一個異常對象是,它將會沿著方法的調用棧逐層回溯,尋找處理這一異常的代碼。

(2)找到能夠處理這種類型異常的方法後,運行時系統把當前異常交給這個方法處理;如果找不到可以捕獲異常的方法,則運行時系統將終止,相應的Java程序也將退出。

(3)捕獲異常是通過try-catch-finally語句實現的。語法為:

try{

...

}catch(ExceptionName1 e){

...

}catch(ExceptionName2 e){

...

}

...

}finally{

...

}

2、聲明拋棄異常:

(1)當Java程序運行時系統得到一個異常對象時,如果一個方法並不知道如何處理所出現的異常,則可在方法聲明時,聲明拋棄異常。

(2)聲明拋棄異常是在一個方法聲明中的throws子句中指明的。如:

public int read() throws IOException{

...

}

其中throws IOException就是聲明拋棄異常,throws後可以跟多個異常類型。

(4)java的handler機制擴展閱讀:

程序設計語言的異常機制:

1、多數語言的異常機制的語法是類似的:用throw或raise拋出一個異常對象(Java或C++等)或一個特殊可擴展的枚舉類型的值(如Ada語言);

2、異常處理代碼的作用范圍用標記子句(try或begin開始的語言作用域)標示其起始,以第一個異常處理子句(catch, except, resuce等)標示其結束;可連續出現若干個異常處理子句,每個處理特定類型的異常。

3、某些語言允許else子句,用於無異常出現的情況。更多見的是finally, ensure子句,無論是否出現異常它都將執行,用於釋放異常處理所需的一些資源。

(1)C++異常處理是資源獲取即初始化(Resource-Acquisition-Is-Initialization)的基礎。

(2)C語言一般認為是不支持異常處理的。Perl語言可選擇支持結構化異常處理(structured exception handling)。

(3)Python語言對異常處理機制是非常普遍深入的,所以想寫出不含try, except的程序非常困難。

參考資料來源:

網路-異常處理

⑤ java異常處理的機制有哪幾種

1 引子
try…catch…finally恐怕是大家再熟悉不過的語句了,而且感覺用起來也是很簡單,邏輯上似乎也是很容易理解。不過,我親自體驗的「教訓」告訴我,這個東西可不是想像中的那麼簡單、聽話。不信?那你看看下面的代碼,「猜猜」它執行後的結果會是什麼?不要往後看答案、也不許執行代碼看真正答案哦。如果你的答案是正確,那麼這篇文章你就不用浪費時間看啦。

package myExample.testException;

public class TestException {

public TestException() {

}

boolean testEx() throws Exception{

boolean ret = true;

try{

ret = testEx1();

}catch (Exception e){

System.out.println("testEx, catch exception");

ret = false;

throw e;

}finally{

System.out.println("testEx, finally; return value="+ret);

return ret;

}

}

boolean testEx1() throws Exception{

boolean ret = true;

try{

ret = testEx2();

if (!ret){

return false;

}

System.out.println("testEx1, at the end of try");

return ret;

}catch (Exception e){

System.out.println("testEx1, catch exception");

ret = false;

throw e;

}

finally{

System.out.println("testEx1, finally; return value="+ret);

return ret;

}

}

boolean testEx2() throws Exception{

boolean ret = true;

try{

int b=12;

int c;

for (int i=2;i>=-2;i--){

c=b/i;

System.out.println("i="+i);

}

return true;

}catch (Exception e){

System.out.println("testEx2, catch exception");

ret = false;

throw e;

}

finally{

System.out.println("testEx2, finally; return value="+ret);

return ret;

}

}

public static void main(String[] args) {

TestException testException1 = new TestException();

try{

testException1.testEx();

}catch(Exception e){

e.printStackTrace();

}

}

}

你的答案是什麼?是下面的答案嗎?

i=2

i=1

testEx2, catch exception

testEx2, finally; return value=false

testEx1, catch exception

testEx1, finally; return value=false

testEx, catch exception

testEx, finally; return value=false

如果你的答案真的如上面所說,那麼你錯啦。^_^,那就建議你仔細看一看這篇文章或者拿上面的代碼按各種不同的情況修改、執行、測試,你會發現有很多事情不是原來想像中的那麼簡單的。

現在公布正確答案:

i=2

i=1

testEx2, catch exception

testEx2, finally; return value=false

testEx1, finally; return value=false

testEx, finally; return value=false

2 基礎知識
2.1 相關概念
例外是在程序運行過程中發生的異常事件,比如除0溢出、數組越界、文件找不到等,這些事件的發生將阻止程序的正常運行。為了加強程序的魯棒性,程序設計時,必須考慮到可能發生的異常事件並做出相應的處理。C語言中,通過使用if語句來判斷是否出現了例外,同時,調用函數通過被調用函數的返回值感知在被調用函數中產生的例外事件並進行處理。全程變數ErroNo常常用來反映一個異常事件的類型。但是,這種錯誤處理機制會導致不少問題。

Java通過面向對象的方法來處理例外。在一個方法的運行過程中,如果發生了例外,則這個方法生成代表該例外的一個對象,並把它交給運行時系統,運行時系統尋找相應的代碼來處理這一例外。我們把生成例外對象並把它提交給運行時系統的過程稱為拋棄(throw)一個例外。運行時系統在方法的調用棧中查找,從生成例外的方法開始進行回朔,直到找到包含相應例外處理的方法為止,這一個過程稱為捕獲(catch)一個例外。

2.2 Throwable類及其子類
用面向對象的方法處理例外,就必須建立類的層次。類 Throwable位於這一類層次的最頂層,只有它的後代才可以做為一個例外被拋棄。圖1表示了例外處理的類層次。

從圖中可以看出,類Throwable有兩個直接子類:Error和Exception。Error類對象(如動態連接錯誤等),由Java虛擬機生成並拋棄(通常,Java程序不對這類例外進行處理);Exception類對象是Java程序處理或拋棄的對象。它有各種不同的子類分別對應於不同類型的例外。其中類RuntimeException代表運行時由Java虛擬機生成的例外,如算術運算例外ArithmeticException(由除0錯等導致)、數組越界例外等;其它則為非運行時例外,如輸入輸出例外IOException等。Java編譯器要求Java程序必須捕獲或聲明所有的非運行時例外,但對運行時例外可以不做處理。

圖1 例外處理的類層次

2.3 異常處理關鍵字
Java的異常處理是通過5個關鍵字來實現的:try,catch,throw,throws,finally。JB的在線幫助中對這幾個關鍵字是這樣解釋的:

Throws: Lists the exceptions a method could throw.

Throw: Transfers control of the method to the exception handler.

Try: Opening exception-handling statement.

Catch: Captures the exception.

Finally: Runs its code before terminating the program.

2.3.1 try語句
try語句用大括弧{}指定了一段代碼,該段代碼可能會拋棄一個或多個例外。

2.3.2 catch語句
catch語句的參數類似於方法的聲明,包括一個例外類型和一個例外對象。例外類型必須為Throwable類的子類,它指明了catch語句所處理的例外類型,例外對象則由運行時系統在try所指定的代碼塊中生成並被捕獲,大括弧中包含對象的處理,其中可以調用對象的方法。

catch語句可以有多個,分別處理不同類的例外。Java運行時系統從上到下分別對每個catch語句處理的例外類型進行檢測,直到找到類型相匹配的catch語句為止。這里,類型匹配指catch所處理的例外類型與生成的例外對象的類型完全一致或者是它的父類,因此,catch語句的排列順序應該是從特殊到一般。

也可以用一個catch語句處理多個例外類型,這時它的例外類型參數應該是這多個例外類型的父類,程序設計中要根據具體的情況來選擇catch語句的例外處理類型。

2.3.3 finally語句
try所限定的代碼中,當拋棄一個例外時,其後的代碼不會被執行。通過finally語句可以指定一塊代碼。無論try所指定的程序塊中拋棄或不拋棄例外,也無論catch語句的例外類型是否與所拋棄的例外的類型一致,finally所指定的代碼都要被執行,它提供了統一的出口。通常在finally語句中可以進行資源的清除工作。如關閉打開的文件等。

2.3.4 throws語句
throws總是出現在一個函數頭中,用來標明該成員函數可能拋出的各種異常。對大多數Exception子類來說,Java 編譯器會強迫你聲明在一個成員函數中拋出的異常的類型。如果異常的類型是Error或 RuntimeException, 或它們的子類,這個規則不起作用, 因為這在程序的正常部分中是不期待出現的。 如果你想明確地拋出一個RuntimeException,你必須用throws語句來聲明它的類型。

2.3.5 throw語句
throw總是出現在函數體中,用來拋出一個異常。程序會在throw語句後立即終止,它後面的語句執行不到,然後在包含它的所有try塊中(可能在上層調用函數中)從里向外尋找含有與其匹配的catch子句的try塊。

3 關鍵字及其中語句流程詳解
3.1 try的嵌套
你可以在一個成員函數調用的外面寫一個try語句,在這個成員函數內部,寫另一個try語句保護其他代碼。每當遇到一個try語句,異常的框架就放到堆棧上面,直到所有的try語句都完成。如果下一級的try語句沒有對某種異常進行處理,堆棧就會展開,直到遇到有處理這種異常的try語句。下面是一個try語句嵌套的例子。

class MultiNest {

static void procere() {

try {

int a = 0;

int b = 42/a;

} catch(java.lang.ArithmeticException e) {

System.out.println("in procere, catch ArithmeticException: " + e);

}

}

public static void main(String args[]) {

try {

procere();

} catch(java.lang. Exception e) {

System.out.println("in main, catch Exception: " + e);

}

}

}

這個例子執行的結果為:

in procere, catch ArithmeticException: java.lang.ArithmeticException: / by zero

成員函數procere里有自己的try/catch控制,所以main不用去處理 ;當然如果如同最開始我們做測試的例子一樣,在procere中catch到異常時使用throw e;語句將異常拋出,那麼main當然還是能夠捕捉並處理這個procere拋出來的異常。例如在procere函數的catch中的System.out語句後面增加throw e;語句之後,執行結果就變為:

in procere, catch ArithmeticException: java.lang.ArithmeticException: / by zero

in main, catch Exception: java.lang.ArithmeticException: / by zero

3.2 try-catch程序塊的執行流程以及執行結果
相對於try-catch-finally程序塊而言,try-catch的執行流程以及執行結果還是比較簡單的。

首先執行的是try語句塊中的語句,這時可能會有以下三種情況:

1. 如果try塊中所有語句正常執行完畢,那麼就不會有其他的「動做」被執行,整個try-catch程序塊正常完成。

2. 如果try語句塊在執行過程中碰到異常V,這時又分為兩種情況進行處理:

² 如果異常V能夠被與try相應的catch塊catch到,那麼第一個catch到這個異常的catch塊(也是離try最近的一個與異常V匹配的catch塊)將被執行;如果catch塊執行正常,那麼try-catch程序塊的結果就是「正常完成」;如果該catch塊由於原因R突然中止,那麼try-catch程序塊的結果就是「由於原因R突然中止(completes abruptly)」。

² 如果異常V沒有catch塊與之匹配,那麼這個try-catch程序塊的結果就是「由於拋出異常V而突然中止(completes abruptly)」。

3. 如果try由於其他原因R突然中止(completes abruptly),那麼這個try-catch程序塊的結果就是「由於原因R突然中止(completes abruptly)」。

3.3 try-catch-finally程序塊的執行流程以及執行結果
try-catch-finally程序塊的執行流程以及執行結果比較復雜。

首先執行的是try語句塊中的語句,這時可能會有以下三種情況:

1. 如果try塊中所有語句正常執行完畢,那麼finally塊的居於就會被執行,這時分為以下兩種情況:

² 如果finally塊執行順利,那麼整個try-catch-finally程序塊正常完成。

² 如果finally塊由於原因R突然中止,那麼try-catch-finally程序塊的結局是「由於原因R突然中止(completes abruptly)」

2. 如果try語句塊在執行過程中碰到異常V,這時又分為兩種情況進行處理:

² 如果異常V能夠被與try相應的catch塊catch到,那麼第一個catch到這個異常的catch塊(也是離try最近的一個與異常V匹配的catch塊)將被執行;這時就會有兩種執行結果:

² 如果catch塊執行正常,那麼finally塊將會被執行,這時分為兩種情況:

² 如果finally塊執行順利,那麼整個try-catch-finally程序塊正常完成。

² 如果finally塊由於原因R突然中止,那麼try-catch-finally程序塊的結局是「由於原因R突然中止(completes abruptly)」

² 如果catch塊由於原因R突然中止,那麼finally模塊將被執行,分為兩種情況:

² 如果如果finally塊執行順利,那麼整個try-catch-finally程序塊的結局是「由於原因R突然中止(completes abruptly)」。

² 如果finally塊由於原因S突然中止,那麼整個try-catch-finally程序塊的結局是「由於原因S突然中止(completes abruptly)」,原因R將被拋棄。

(注意,這里就正好和我們的例子相符合,雖然我們在testEx2中使用throw e拋出了異常,但是由於testEx2中有finally塊,而finally塊的執行結果是complete abruptly的(別小看這個用得最多的return,它也是一種導致complete abruptly的原因之一啊——後文中有關於導致complete abruptly的原因分析),所以整個try-catch-finally程序塊的結果是「complete abruptly」,所以在testEx1中調用testEx2時是捕捉不到testEx1中拋出的那個異常的,而只能將finally中的return結果獲取到。

如果在你的代碼中期望通過捕捉被調用的下級函數的異常來給定返回值,那麼一定要注意你所調用的下級函數中的finally語句,它有可能會使你throw出來的異常並不能真正被上級調用函數可見的。當然這種情況是可以避免的,以testEx2為例:如果你一定要使用finally而且又要將catch中throw的e在testEx1中被捕獲到,那麼你去掉testEx2中的finally中的return就可以了。

這個事情已經在OMC2.0的MIB中出現過啦:伺服器的異常不能完全被反饋到客戶端。)

² 如果異常V沒有catch塊與之匹配,那麼finally模塊將被執行,分為兩種情況:

² 如果finally塊執行順利,那麼整個try-catch-finally程序塊的結局就是「由於拋出異常V而突然中止(completes abruptly)」。

² 如果finally塊由於原因S突然中止,那麼整個try-catch-finally程序塊的結局是「由於原因S突然中止(completes abruptly)」,異常V將被拋棄。

3. 如果try由於其他原因R突然中止(completes abruptly),那麼finally塊被執行,分為兩種情況:

² 如果finally塊執行順利,那麼整個try-catch-finally程序塊的結局是「由於原因R突然中止(completes abruptly)」。

² 如果finally塊由於原因S突然中止,那麼整個try-catch-finally程序塊的結局是「由於原因S突然中止(completes abruptly)」,原因R將被拋棄。

3.4 try-catch-finally程序塊中的return
從上面的try-catch-finally程序塊的執行流程以及執行結果一節中可以看出無論try或catch中發生了什麼情況,finally都是會被執行的,那麼寫在try或者catch中的return語句也就不會真正的從該函數中跳出了,它的作用在這種情況下就變成了將控制權(語句流程)轉到finally塊中;這種情況下一定要注意返回值的處理。

例如,在try或者catch中return false了,而在finally中又return true,那麼這種情況下不要期待你的try或者catch中的return false的返回值false被上級調用函數獲取到,上級調用函數能夠獲取到的只是finally中的返回值,因為try或者catch中的return語句只是轉移控制權的作用。

3.5 如何拋出異常
如果你知道你寫的某個函數有可能拋出異常,而你又不想在這個函數中對異常進行處理,只是想把它拋出去讓調用這個函數的上級調用函數進行處理,那麼有兩種方式可供選擇:

第一種方式:直接在函數頭中throws SomeException,函數體中不需要try/catch。比如將最開始的例子中的testEx2改為下面的方式,那麼testEx1就能捕捉到testEx2拋出的異常了。

boolean testEx2() throws Exception{

boolean ret = true;

int b=12;

int c;

for (int i=2;i>=-2;i--){

c=b/i;

System.out.println("i="+i);

}

return true;

}

第二種方式:使用try/catch,在catch中進行一定的處理之後(如果有必要的話)拋出某種異常。例如上面的testEx2改為下面的方式,testEx1也能捕獲到它拋出的異常:

boolean testEx2() throws Exception{

boolean ret = true;

try{

int b=12;

int c;

for (int i=2;i>=-2;i--){

c=b/i;

System.out.println("i="+i);

}

return true;

}catch (Exception e){

System.out.println("testEx2, catch exception");

Throw e;

}

}

第三種方法:使用try/catch/finally,在catch中進行一定的處理之後(如果有必要的話)拋出某種異常。例如上面的testEx2改為下面的方式,testEx1也能捕獲到它拋出的異常:

boolean testEx2() throws Exception{

boolean ret = true;

try{

int b=12;

int c;

for (int i=2;i>=-2;i--){

c=b/i;

System.out.println("i="+i);

throw new Exception("aaa");

}

return true;

}catch (java.lang.ArithmeticException e){

System.out.println("testEx2, catch exception");

ret = false;

throw new Exception("aaa");

}finally{

System.out.println("testEx2, finally; return value="+ret);

}

}

4 關於abrupt completion
前面提到了complete abruptly(暫且理解為「突然中止」或者「異常結束」吧),它主要包含了兩種大的情形:abrupt completion of expressions and statements,下面就分兩種情況進行解釋。

4.1 Normal and Abrupt Completion of Evaluation
每一個表達式(expression)都有一種使得其包含的計算得以一步步進行的正常模式,如果每一步計算都被執行且沒有異常拋出,那麼就稱這個表達式「正常結束(complete normally)」;如果這個表達式的計算拋出了異常,就稱為「異常結束(complete abruptly)」。異常結束通常有一個相關聯的原因(associated reason),通常也就是拋出一個異常V。

與表達式、操作符相關的運行期異常有:

² A class instance creation expression, array creation expression , or string concatenation operatior expression throws an OutOfMemoryError if there is insufficient memory available.

² An array creation expression throws a NegativeArraySizeException if the value of any dimension expression is less than zero.

² A field access throws a NullPointerException if the value of the object reference expression is null.

² A method invocation expression that invokes an instance method throws a NullPointerException if the target reference is null.

² An array access throws a NullPointerException if the value of the array reference expression is null.

² An array access throws an if the value of the array index expression is negative or greater than or equal to the length of the array.

² A cast throws a ClassCastException if a cast is found to be impermissible at run time.

² An integer division or integer remainder operator throws an ArithmeticException if the value of the right-hand operand expression is zero.

² An assignment to an array component of reference type throws an ArrayStoreException when the value to be assigned is not compatible with the component type of the array.

4.2 Normal and Abrupt Completion of Statements
正常情況我們就不多說了,在這里主要是列出了abrupt completion的幾種情況:

² break, continue, and return 語句將導致控制權的轉換,從而使得statements不能正常地、完整地執行。

² 某些表達式的計算也可能從java虛擬機拋出異常,這些表達式在上一小節中已經總結過了;一個顯式的的throw語句也將導致異常的拋出。拋出異常也是導致控制權的轉換的原因(或者說是阻止statement正常結束的原因)。

如果上述事件發生了,那麼這些statement就有可能使得其正常情況下應該都執行的語句不能完全被執行到,那麼這些statement也就是被稱為是complete abruptly.

導致abrupt completion的幾種原因:

² A break with no label

² A break with a given label

² A continue with no label

² A continue with a given label

² A return with no value

² A return with a given value A

² throw with a given value, including exceptions thrown by the Java virtual machine

5 關於我們的編程的一點建議
弄清楚try-catch-finally的執行情況後我們才能正確使用它。

如果我們使用的是try-catch-finally語句塊,而我們又需要保證有異常時能夠拋出異常,那麼在finally語句中就不要使用return語句了(finally語句塊的最重要的作用應該是釋放申請的資源),因為finally中的return語句會導致我們的throw e被拋棄,在這個try-catch-finally的外面將只能看到finally中的返回值(除非在finally中拋出異常)。(我們需要記住:不僅throw語句是abrupt completion 的原因,return、break、continue等這些看起來很正常的語句也是導致abrupt completion的原因。)

⑥ Java異常機制是什麼

異常指不期而至的各種狀況,如:文件找不到、網路連接失敗、非法參數等。異常是一個事件,它發生在程序運行期間,干擾了正常的指令流程。Java通 過API中Throwable類的眾多子類描述各種不同的異常。因而,Java異常都是對象,是Throwable子類的實例,描述了出現在一段編碼中的 錯誤條件。當條件生成時,錯誤將引發異常。
一、相關知識
1、在 Java 中,所有的異常都有一個共同的祖先 Throwable(可拋出)。Throwable 指定代碼中可用異常傳播機制通過 Java 應用程序傳輸的任何問題的共性。
Throwable: 有兩個重要的子類:Exception(異常)和 Error(錯誤),二者都是 Java 異常處理的重要子類,各自都包含大量子類。
Error(錯誤):是程序無法處理的錯誤,表示運行應用程序中較嚴重問題。大多數錯誤與代碼編寫者執行的操作無關,而表示代碼運行時 JVM(Java 虛擬機)出現的問題。例如,Java虛擬機運行錯誤(Virtual MachineError),當 JVM 不再有繼續執行操作所需的內存資源時,將出現 OutOfMemoryError。這些異常發生時,Java虛擬機(JVM)一般會選擇線程終止。這些錯誤表示故障發生於虛擬機自身、或者發生在虛擬機試圖執行應用時,如Java虛擬機運行錯誤(Virtual MachineError)、類定義錯誤(NoClassDefFoundError)等。這些錯誤是不可查的,因為它們在應用程序的控制和處理能力之 外,而且絕大多數是程序運行時不允許出現的狀況。對於設計合理的應用程序來說,即使確實發生了錯誤,本質上也不應該試圖去處理它所引起的異常狀況。在 Java中,錯誤通過Error的子類描述。
Exception(異常):是程序本身可以處理的異常。Exception 類有一個重要的子類 RuntimeException。RuntimeException 類及其子類表示「JVM 常用操作」引發的錯誤。例如,若試圖使用空值對象引用、除數為零或數組越界,則分別引發運行時異常(NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException。
注意:異常和錯誤的區別:異常能被程序本身可以處理,錯誤是無法處理。
2、通常,Java的異常(包括Exception和Error)分為可查的異常(checked exceptions)和不可查的異常(unchecked exceptions)。
可查異常(編譯器要求必須處置的異常):正確的程序在運行中,很容易出現的、情理可容的異常狀況。可查異常雖然是異常狀況,但在一定程度上它的發生是可以預計的,而且一旦發生這種異常狀況,就必須採取某種方式進行處理。除了RuntimeException及其子類以外,其他的Exception類及其子類都屬於可查異常。這種異常的特點是Java編譯器會檢查它,也就是說,當程序中可能出現這類異常,要麼用try-catch語句捕獲它,要麼用throws子句聲明拋出它,否則編譯不會通過。
不可查異常(編譯器不要求強制處置的異常):包括運行時異常(RuntimeException與其子類)和錯誤(Error)。
3、Exception 這種異常分兩大類運行時異常和非運行時異常(編譯異常)。程序中應當盡可能去處理這些異常。
運行時異常:都是RuntimeException類及其子類異常,如NullPointerException(空指針異常)、IndexOutOfBoundsException(下標越界異常)等,這些異常是不檢查異常,程序中可以選擇捕獲處理,也可以不處理。這些異常一般是由程序邏輯錯誤引起的,程序應該從邏輯角度盡可能避免這類異常的發生。運行時異常的特點是Java編譯器不會檢查它,也就是說,當程序中可能出現這類異常,即使沒有用try-catch語句捕獲它,也沒有用throws子句聲明拋出它,也會編譯通過。
非運行時異常 (編譯異常):是RuntimeException以外的異常,類型上都屬於Exception類及其子類。從程序語法角度講是必須進行處理的異常,如果不處理,程序就不能編譯通過。如IOException、SQLException等以及用戶自定義的Exception異常,一般情況下不自定義檢查異常。
二、處理機制
在 Java 應用程序中,異常處理機制為:拋出異常,捕捉異常。
拋出異常:當一個方法出現錯誤引發異常時,方法創建異常對象並交付運行時系統,異常對象中包含了異常類型和異常出現時的程序狀態等異常信息。運行時系統負責尋找處置異常的代碼並執行。
捕獲異常:在方法拋出異常之後,運行時系統將轉為尋找合適的異常處理器(exception handler)。潛在的異常處理器是異常發生時依次存留在調用棧中的方法的集合。當異常處理器所能處理的異常類型與方法拋出的異常類型相符時,即為合適 的異常處理器。運行時系統從發生異常的方法開始,依次回查調用棧中的方法,直至找到含有合適異常處理器的方法並執行。當運行時系統遍歷調用棧而未找到合適 的異常處理器,則運行時系統終止。同時,意味著Java程序的終止。
對於運行時異常、錯誤或可查異常,Java技術所要求的異常處理方式有所不同。
由於運行時異常的不可查性,為了更合理、更容易地實現應用程序,Java規定,運行時異常將由Java運行時系統自動拋出,允許應用程序忽略運行時異常。
對於方法運行中可能出現的Error,當運行方法不欲捕捉時,Java允許該方法不做任何拋出聲明。因為,大多數Error異常屬於永遠不能被允許發生的狀況,也屬於合理的應用程序不該捕捉的異常。
對於所有的可查異常,Java規定:一個方法必須捕捉,或者聲明拋出方法之外。也就是說,當一個方法選擇不捕捉可查異常時,它必須聲明將拋出異常。
能夠捕捉異常的方法,需要提供相符類型的異常處理器。所捕捉的異常,可能是由於自身語句所引發並拋出的異常,也可能是由某個調用的方法或者Java運行時 系統等拋出的異常。也就是說,一個方法所能捕捉的異常,一定是Java代碼在某處所拋出的異常。簡單地說,異常總是先被拋出,後被捕捉的。
任何Java代碼都可以拋出異常,如:自己編寫的代碼、來自Java開發環境包中代碼,或者Java運行時系統。無論是誰,都可以通過Java的throw語句拋出異常。
從方法中拋出的任何異常都必須使用throws子句。
捕捉異常通過try-catch語句或者try-catch-finally語句實現。
總體來說,Java規定:對於可查異常必須捕捉、或者聲明拋出。允許忽略不可查的RuntimeException和Error。

⑦ 請問,誰有java日誌中的處理者(handler)的相關信息

你想要什麼樣的信息?

Handler 對象從 Logger 中獲取日誌信息,並將這些信息導出。例如,它可將這些信息寫入控制台或文件中,也可以將這些信息發送到網路日誌服務中,或將其轉發到操作系統日誌中。

可通過執行 setLevel(Level.OFF) 來禁用 Handler,並可通過執行適當級別的 setLevel 來重新啟用。

Handler 類通常使用 LogManager 屬性來設置 Handler 的 Filter、Formatter 和 Level 的默認值。

java.util.logging.Handler
java.util.logging.MemoryHandler
java.util.logging.StreamHandler
java.util.logging.ConsoleHandler
java.util.logging.FileHandler
java.util.logging.SocketHandler

默認的日誌方式是xml格式

⑧ Android AIDL進程間通信跟Handler機制有什麼區別有哪個技術已經漸漸被淘汰了嗎

您好:
AIDL(Android Interface Definition Language)是一種介面定義語言,編譯器通過*.aidl文件的描述信息生成符合通信協議的Java代碼,我們無需自己去寫這段繁雜的代碼,只需要在需要的時候調用即可,通過這種方式我們就可以完成進程間的通信工作。
Handler通俗一點講就是用來在各個線程之間發送數據的處理對象。在任何線程中,只要獲得了另一個線程的handler,則可以通過 handler.sendMessage(message)方法向那個線程發送數據。基於這個機制,我們在處理多線程的時候可以新建一個thread,這個thread擁有UI線程中的一個handler。當thread處理完一些耗時的操作後通過傳遞過來的handler像ui線程發送數據,由UI線程去更新界面。

⑨ Java異常機制是什麼

一、異常的關鍵字:

一般來說,異常的關鍵字有:try、catch、finally、throw、throws。
網上的資料對這幾個關鍵字是這樣解釋的:
try: Opening exception-handling statement.
catch: Captures the exception.
finally: Runs its code before terminating the program.
throws: Lists the exceptions a method could throw.
Throw: Transfers control of the method to the exception handler.

try語句
try語句用大括弧{}指定了一段代碼,該段代碼可能會拋棄一個或多個例外。
catch語句
catch語句的參數類似於方法的聲明,包括一個例外類型和一個例外對象。例外類型必須為Throwable類的子類,它指明了catch語句所處理的例外類型,例外對象則由運行時系統在try所指定的代碼塊中生成並被捕獲,大括弧中包含對象的處理,其中可以調用對象的方法。
catch語句可以有多個,分別處理不同類的例外。Java運行時系統從上到下分別對每個catch語句處理的例外類型進行檢測,直到找到類型相匹配的catch語句為止。這里,類型匹配指catch所處理的例外類型與生成的例外對象的類型完全一致或者是它的父類,因此,catch語句的排列順序應該是從特殊到一般。也可以用一個catch語句處理多個例外類型,這時它的例外類型參數應該是這多個例外類型的父類,程序設計中要根據具體的情況來選擇catch語句的例外處理類型。
finally語句
try所限定的代碼中,當拋棄一個例外時,其後的代碼不會被執行。通過finally語句可以指定一塊代碼。無論try所指定的程序塊中拋棄或不拋棄例外,也無論catch語句的例外類型是否與所拋棄的例外的類型一致,finally所指定的代碼都要被執行,它提供了統一的出口。通常在finally語句中可以進行資源的清除工作。如關閉打開的文件等。
throws語句
throws總是出現在一個函數頭中,用來標明該成員函數可能拋出的各種異常。對大多數Exception子類來說,Java 編譯器會強迫你聲明在一個成員函數中拋出的異常的類型。如果異常的類型是Error或 RuntimeException, 或它們的子類,這個規則不起作用, 因為這在程序的正常部分中是不期待出現的。 如果你想明確地拋出一個RuntimeException,你必須用throws語句來聲明它的類型
throw語句
throw總是出現在函數體中,用來拋出一個異常。程序會在throw語句後立即終止,它後面的語句執行不到,然後在包含它的所有try塊中(可能在上層調用函數中)從里向外尋找含有與其匹配的catch子句的try塊。

其實,我個人覺得,簡單的來說:throws與throw從拼寫上只相差一個s,但是功能、作用上有很大的區別。throws用於在方法和類處聲明可能拋出的所有異常信息。throw而throw就是單個語句拋出異常,是指拋出的一個具體的異常類型,使用在方法(類)的內部。
如:
………………………………………………………………………………………………………
public class showUI throws Exception(){
public void tbstudy throws Exception(){
****;//
try{
/* 這里是要處理的異常 */
}
Catch(Exception of){
System.out.println(of);//列印出異常
}
}

………………………………………………………………………………………………………
throws通常不用顯示的捕獲異常,可由系統自動將所有捕獲的異常信息拋給上級方法(即調用該方法或類的所有地方);
throw則需要用戶自己捕獲相關的異常,而後再對其進行相關處理(如列印異常的地方,類型等),最後將處理後的異常信息拋出。
他們對異常處理方式也不同.throws對異常不處理,誰調用誰處理,throws的Exception的取值范圍要大於方法內部異常的最大范圍,而cathch的范圍又要大於throws的Exception的范圍;throw 主動拋出自定義異常類對象。

二、異常繼承體系

異常的繼承結構

三、java處理異常方式
在java代碼中如果發生異常,jvm(java虛擬機)會拋出異常對象,導致程序代碼中斷,這個時候jvm在做的操作就是:創建異常對象,然後拋出,比如:

1.int i= 1;
2.int j = 0;
3.int res = 0;
4.res = i/j;//除0錯誤
5.System.out.println(res);

這5句代碼運行到第四句會中斷,因為jvm拋出了異常

2.throw的作用:手動拋出異常。有時候有些錯誤在jvm看來不是錯誤,比如:
1. int age = 0;
2. age = -100;
3.System.out.println(age);
很正常的整形變數賦值,但是在我們眼中看來就不正常,誰的年齡會是負的呢?!所以我們需要自己手動引發異常,這就是throw的作用
int age = 0;
age = -100;
if(age<0){
Exception e = new Exception(); //創建異常對象
throw e; //拋出異常
}
System.out.println(age);

java中的異常機制

異常機制是指當程序出現錯誤後,程序如何處理。具體來說,異常機制提供了程序退出的安全通道。當出現錯誤後,程序執行的流程發生改變,程序的控制權轉移到異常處理器。
傳統的處理異常的辦法是,函數返回一個特殊的結果來表示出現異常(通常這個特殊結果是大家約定俗稱的),調用該函數的程序負責檢查並分析函數返回的結果。這樣做有如下的弊端:例如函數返回-1代表出現異常,但是如果函數確實要返回-1這個正確的值時就會出現混淆;可讀性降低,將程序代碼與處理異常的代碼混疊在一起;由調用函數的程序來分析錯誤,這就要求客戶程序員對庫函數有很深的了解。

在使用File類的方法時,如正在將U盤裡面的照片復制到電腦里時,有人將U盤拔掉了。這時我們的復製程序就會出錯,即拋出異常。當出現程序無法控制的外部環境問題(用戶提供的文件不存在或者創建文件時已有同名文件存在,文件內容損壞,網路不可用...)時,JAVA就會用異常對象來描述。
異常情況通常有三大類:
(1)檢查性異常:java.lang.Exception
(2)運行期異常:java.lang.RuntimeException
(3)錯誤:java.lang.Error
它們都是java.lang.Throwable類的子孫類。如右圖:
Throwable 類是 Java 語言中所有錯誤和異常類的父類,對於具體的異常,不應該使用Throwable類,而應該使用其他三者之一。
檢查性異常------程序正確,但因為外在的環境條件不滿足引發。例如:用戶錯誤及I/O問題----程序試圖打開一個並不存在的遠程Socket埠。這不是程序本身的邏輯錯誤,而很可能是遠程機器名字錯誤(用戶拼寫錯誤)。對商用軟體系統,程序開發者必須考慮並處理這個問題。JAVA編譯器強制要求處理這類異常,如果不捕獲這類異常,程序將不能被編譯。
運行期異常------這意味著程序存在bug,如數組越界,0被除,入參不滿足規范.....這類異常需要更改程序來避免,JAVA編譯器強制要求處理這類異常。用來表示設計或實現方面的問題,如數組越界等。因為設計和實現正確的程序不會引發這類異常,所以常常不處理它。發生這類異常時,運行時環境會輸出一條信息,提示用戶修正錯誤。
錯誤------一般很少見,也很難通過程序解決。它可能源於程序的bug,但一般更可能源於環境問題,如內存耗盡。錯誤在程序中無須處理,而有運行環境處理。Error表示很難恢復的錯誤,如內存越界。一般不期望用戶程序來處理,即使程序員有能力處理這種錯誤,也還是交給系統處理為好。

閱讀全文

與java的handler機制相關的資料

熱點內容
現代鋼琴教程pdf 瀏覽:25
客戶端框架源碼 瀏覽:210
python自動辦公能幹嘛 瀏覽:873
程序員追愛 瀏覽:252
程序員邏輯故事 瀏覽:768
加密icsot23i2c 瀏覽:713
你們有什麼好的解壓軟體 瀏覽:607
常州空氣壓縮機廠家 瀏覽:241
安卓如何關閉app內彈出的更新提示 瀏覽:409
e4a寫的app怎麼裝蘋果手機 瀏覽:201
海立壓縮機海信系 瀏覽:210
社保如何在app上合並 瀏覽:220
小米加密照片後綴 瀏覽:236
我的世界網易手機怎麼創伺服器 瀏覽:978
載入單頁源碼 瀏覽:930
阿里雲伺服器seo 瀏覽:777
海洋斗什麼時候上線安卓 瀏覽:86
中行app如何查每日匯款限額 瀏覽:840
輸入伺服器sn是什麼意思 瀏覽:725
sha1演算法java 瀏覽:90