ABAP异常处理
異常處理??????????????????
基于類的異常是從6.10版本開始,它們是以異常類實例方式來實現(xiàn)。異常類是系統(tǒng)預(yù)先定義好的全局類或者是由用戶自定義的局部或全局的類。
在sap6.10版本里,exception classes已經(jīng)取代了catchable runtime errors
基于類的異常exception classes?捕獲
DATA?myref?TYPE?REF?TO?cx_sy_arithmetic_error.
DATA?err_text?TYPE?string.
DATA?result?TYPE?i.
TRY.
??? result =?1?/?0.
CATCH?cx_sy_arithmetic_error?INTO?myref.
??? err_text = myref->get_text( ).
ENDTRY.
這個寫法與java是相似的
使用老式方式捕獲catchable runtime errors
catchable runtime errors
CATCH SYSTEM-EXCEPTIONS?[exc1 = n1 exc2 = n2 ...]?
????????????????????????????????? [OTHERS?= n_others].
? [statement_block]
ENDCATCH.
OTHERS接收所有前面異常列表?n1 n2 …未捕獲到的異常。
?
DATA: result?TYPE?i.
CATCH?SYSTEM-EXCEPTIONS?arithmetic_errors =?5.
??? result =?1?/?0.???
ENDCATCH.
IF?sy-subrc =?5.
??WRITE?/?'Division by zero!'.
ENDIF.
現(xiàn)一般不用這種方式了,而是這樣:
??DATA?result?TYPE?p?DECIMALS?2.
??DATA?oref?TYPE REF TO?cx_root.
??DATA text TYPE?string.
??DATA i TYPE i.
??TRY?.
??????i?=?1?/?0.
??CATCH?cx_root?INTO?oref.
??????text?=?oref->get_text( ).
??????WRITE:?'---'?,?text.
??????RAISE EXCEPTION?oref.”注:如果有此句,則不能放在Function中,否則報:Old and class-based exceptions must not be used the same time
??ENDTRY.
向上拋出異常
如果Form中出現(xiàn)了運(yùn)行時錯誤,但Form簽名又沒有使用RAISING向上拋,則程序會直接掛掉,所以最好是向上拋
FORM?subform?RAISING?cx_static_check cx_dynamic_check.
...
ENDFORM.
?
Funcion函數(shù)不會主動向外拋出運(yùn)行時錯誤,所以要先在Function手動CATCH,再手動向外拋,如果出現(xiàn)運(yùn)行時錯誤不拋出,則Function與會直接宕掉:
手動觸發(fā)異常(類異常)
RAISE EXCEPTION?{ {TYPE cx_class [EXPORTING p1 = a1 p2 = a2 ...]}
??????????????? | oref }.
EXPORTING選項表示的是異常類構(gòu)造函數(shù)的參數(shù)。
?
DATA: exc??TYPE?REF?TO?cx_sy_dynamic_osql_semantics,
??????text?TYPE?string.
TRY.
??RAISE?EXCEPTION?TYPE?cx_sy_dynamic_osql_semantics
?????????????????????EXPORTING?textid = cx_sy_dynamic_osql_semantics=>unknown_table_name token? =?'Test'.
??CATCH?cx_sy_dynamic_osql_semantics?INTO?exc.
????text?= exc->get_text( ).
????MESSAGE?text?TYPE?'I'.
ENDTRY.
6.1版本以后,TRY…ENDTRY結(jié)構(gòu):
TRY.
??? [try_block]
CATCH?cx_class1 cx_class2 ... [INTO oref].
??? [catch_block]
??? ...
[CLEANUP?[INTO oref].
??? [cleanup_block]]
ENDTRY.
CLEARUP是在所在的TRY CATCH發(fā)生了異常,但在本TRY CATCH中無法捕獲,異常再次向上遞交給上層TRY CATCH前被執(zhí)行的,它不同于Java中的finally
PARAMETERS?number?TYPE?i.
DATA?result?TYPE?p?DECIMALS?2.
DATA?oref?TYPE?REF?TO?cx_root.
DATA?text?TYPE?string.
START-OF-SELECTION.
??TRY.
??????IF?ABS(?number?) >?100.
????????RAISE?EXCEPTION?TYPE?cx_demo_abs_too_large.
??????ENDIF.
??????TRY.
????????? result =?1?/?number.
??????????WRITE: /?'Result of division:', result.
????????? result =?SQRT(?number?).
??????????WRITE: /?'Result of square root:', result.
????????CATCH?cx_sy_zerodivide?INTO?oref."輸出0時會在這里捕獲
??????????text?= oref->get_text( ).
??????????CONCATENATE?'CATCH cx_sy_zerodivide : '?text?INTO?text.
????????CLEANUP."當(dāng)內(nèi)層TRY發(fā)生了異常,且沒有被捕獲到,拋到外層TRY前會被執(zhí)行
??????????CLEAR?result.
??????????WRITE: /?'cleanup'.
??????ENDTRY.
????CATCH?cx_sy_arithmetic_error?INTO?oref."輸入負(fù)數(shù)會在這里捕獲
??????text?= oref->get_text( ).
??????CONCATENATE?'CATCH cx_sy_arithmetic_error : '?text?INTO?text.
????CATCH?cx_root?INTO?oref."輸入的數(shù)大于100時會在這里捕獲
??????text?= oref->get_text( ).
???????CONCATENATE?'CATCH cx_root : '?text?INTO?text.
??ENDTRY.
??IF?NOT?text?IS?INITIAL.
????WRITE?/?text.
??ENDIF.
??WRITE: /?'Final result:', result.
?
異常的觸發(fā):
l??運(yùn)行出錯時,系統(tǒng)會自動觸發(fā)預(yù)定好的異常類(類似于Java中的運(yùn)行時異常,6.10前是觸發(fā)的預(yù)定好的錯誤)
l??可以使用RAISE EXCEPTION手動觸發(fā)異常(類似Java的throw)
l??對于局部的類的METHODS、過程FORM后加上RAISING?選項來聲明要拋出的異常,向上繼續(xù)拋出(類似Java的throws),全局的函數(shù)異常在Exceptions標(biāo)簽里如下設(shè)置:
在代碼中手動直接拋出異常即可:
?
l??類的靜態(tài)構(gòu)造函數(shù)不能拋出異常
l??event handler定義時不能拋出異常
l??使用SUBMIT ... AND RETURN?或者CALL TRANSACTION調(diào)用程序時,不能將異常傳播給調(diào)用者,因為異常對象是與程序的內(nèi)部會話綁定的
?
三類異常:
l??CX_STATIC_CHECK
l??CX_DYNAMIC_CHECK
l??CX_NO_CHECK
具體的異常類繼承結(jié)構(gòu)請查看SAP幫助,輸入“EXCEPTION”
類比:CX_NO_CHECK類似于Java中的Error,CX_DYNAMIC_CHECK類似于Java中的RuntimeException,CX_STATIC_CHECK類似于Java檢測性異常
?
CX_STATIC_CHECK是一個抽象類,一般自己定的異常都要求繼承于它。在程序中使用RAISE EXCEPTION?手動拋出這類異常時,方法或過程接口上一定要顯示的通過RAISING?來向上層拋出異常(或者直接在方法或過程中進(jìn)行處理也可以),否則靜態(tài)編譯時就會出現(xiàn)警告。
?
CX_NO_CHECK類型的異常一般表示系統(tǒng)資源不足引起的,不能在方法或過程接口后面拋出CX_NO_CHECK類型的異常,它會被隱含的拋出與傳遞。系統(tǒng)中已有預(yù)定義這類異常。
?
如果程序邏輯能夠排除可能性的潛在性錯,相應(yīng)的異常就可能不用處理或繼續(xù)拋出,此類情況下可以使用CX_DYNAMIC_CHECK類型的異常,這與Java中的運(yùn)行時異常相似,一旦發(fā)生也該類異常,表示問題出現(xiàn)在程序的本身設(shè)計上,程序設(shè)計不嚴(yán)謹(jǐn)(如沒有判斷空指針問題)。ABAP大多數(shù)的系統(tǒng)預(yù)定義的異類都是屬于該類型異常,這就意味著不需要處理或拋出ABAP語句可能出現(xiàn)的每一種異常,但一旦發(fā)生了該類異常,則表示程序的邏輯出現(xiàn)了問題,程序執(zhí)行的結(jié)果將不會在正確。
?
異常類可以被定義成全局的類或者是局部的異常類,全局異常類名稱以CX_, YCX_, ZCX_為前綴。系統(tǒng)里預(yù)定義好的全局異常類都是能CX_SY_為前綴來命名的。
?
如果是通過Class Builder創(chuàng)建的全局異常類時,由于構(gòu)造器是默認(rèn)創(chuàng)建好的,不能傳遞參數(shù),所以異常文本ID只能通過TEXTID傳遞,但局部異常類沒有這個限制。
?
如果在拋出的異常類在構(gòu)造的過程中(構(gòu)造函數(shù)中)發(fā)生了異常,則會使用CX_SY_NO_HANDLER異常來代替原來的異常實例。
?
函數(shù)異常的定義、拋出、與處理
?
CALLFUNCTION時一定不能省略Exceptions選項(EXCEPTIONS表示函數(shù)接口需要拋出異常,如果函數(shù)里拋出了異常,但調(diào)用時接口上沒有加上該選項,則程序運(yùn)行時會中斷),否則異常不能捕獲,運(yùn)行時會出錯。其實Exception先項就相當(dāng)于TRY ... CATCH...
總結(jié)
- 上一篇: 【备忘】外币评估数据存储表
- 下一篇: 【MM配置】Movement Type