Java和SAP ABAP的异常处理
Recently I am prepare an internal training and have been racking my brains to find a real example for my attendees about writting a “correct” program which gets rejected by compiler. The tricky point here is as a programmer, we always treat compiler as our god: if compiler complains that our program has errors, then we are wrong. Programmers tend to believe in that compiler will NEVER make mistakes.
Checked and unchecked exception in Java
Let’s see the following Java code:
package exception;
import java.sql.SQLException;
public class ExceptionForQuiz<T extends Exception> {
private void pleaseThrow(final Exception t) throws T {
throw (T) t;
}
public static void main(final String[] args) {
try {
new ExceptionForQuiz<RuntimeException>().pleaseThrow(new SQLException());
}
catch( final SQLException ex){
System.out.println("Jerry print");
ex.printStackTrace();
}
}
}
What result this program will generate? Let’s analyze it step by step.
(1) The class ExceptionForQuiz uses a generic typing syntax extends to declare a bound that T only accepts Exception and its sub classes. As a result in my main method code the creation of new ExceptionForQuiz via the below code is legal since according to JDK source code, RuntimeException is subclass of Exception.
new ExceptionForQuiz()
Also keep in mind that RuntimeException is a kind of Unchecked exception ( do not need to be declared in method where it might be raised ), which will be compared with ABAP exception later.
(2) According to Java Document, the type parameter in generic type declaration will be replaced by its bound during compile, in my exception RuntimeException will be replaced by Exception. This is called Type Erasure. As a result, let’s forget about the try – catch for the moment. This is original code:
This is the code decompiled from ExceptionForQuiz.class:
You can observe the fact of type erasure clearly. You can also check the byte code by command javap, where the RuntimeException is erased.
(3) Now let’s see the result of this quiz. The correct answer is: this program cannot pass compile! Compiler considers that SQLException could never have possibility to be raised from within TRY block.
Unfortunately, this is what I would like to do: raise SQLException via method pleaseThrow and catch it in catch block.
How to achieve my requirement?
Just change one line as highlighted below. Instead of catching SQLException, I now catch RuntimeException in order to pacify the compiler.
Now there is no compilation error any more but when executing it, I find the raised SQLException still cannot be caught as I expect. My println is not executed at all.
I have to catch the Exception, the super class of all other exception instead ( like CX_ROOT in ABAP ), which is not a good practice in exception handling area.
Handleable and Unhandleable Exception in ABAP
You can find both definition in ABAP help.
Let’s now do the similar exercise as we did previous in Java. Create a method with below signature.
Now make the first test:
DATA(lo_test) = NEW zcl_exception_test( ).
DATA: lo_exception TYPE REF TO cx_atd_exception.
CREATE OBJECT lo_exception.
WRITE:/ 'First test' COLOR COL_NEGATIVE.
TRY.
lo_test->please_throw( lo_exception ).
CATCH cx_atd_exception INTO DATA(exception1).
WRITE:/ 'Jerry: ' , exception1->get_text( ).
ENDTRY.
It works as expected, the raised exception is caught.
Now the second test:
DATA: lo_exception2 TYPE REF TO cx_sql_exception.
CREATE OBJECT lo_exception2.
WRITE:/ 'Second test' COLOR COL_NEGATIVE.
TRY.
lo_test->please_throw( lo_exception2 ).
CATCH cx_sql_exception INTO DATA(exception).
WRITE:/ 'In catch sql exception:' , exception->get_text( ).
ENDTRY.
The code is exactly the same as the first test, except that the exception is changed from CX_ATD_EXCEPTION to CX_SQL_EXCEPTION. And result for the second test, 囧 …
In order to make this CX_SQL_EXCEPTION caught-able, I have to write the same dirty code as we did in Java example:
Although this time it works, but what is the reason of the different behaviors of these two examples?
The error message and short dump description have already given us a hint. CX_ATD_EXCEPTION’s super class: CX_NO_CHECK. As its description says, it is not necessary to manually declare it in method signature using RAISING keyword.
And CX_SQL_EXCEPTION’s super class: CX_STATIC_CHECK
As a result now we have another solution: Create another version of PLEASE_THROW method with RAISING keyword:
Use this new version and now CX_SQL_EXCEPTION could be caught:
WRITE:/ 'Third test' COLOR COL_NEGATIVE.
TRY.
lo_test->please_throw2( lo_exception2 ).
CATCH cx_sql_exception INTO DATA(exception3).
WRITE:/ 'In catch sql exception:' , exception3->get_text( ).
ENDTRY.
- JQuery笔记(五) 圆角表格的效果
- tomcat内存溢出问题记录
- 微信小程序开放 Wi-Fi、NFC 连接能力,未来可直接刷地铁?
- 2017奇葩机器人大盘点:Sophia想生孩子,Atlas后空翻,贝佐斯骑高达
- silverlight:分享一个不错的自定义布局CollectionFlow(可用于制作相册的哦!)
- 无法取得ConnectionSettings的问题
- DataTable,List去重复记录的方法
- Uploadify的一点总结
- 自动驾驶时代,中国移动要以怎样的姿势进入?
- JQuery中文日期控件
- Silverlight中的帧
- 窗口自动弹出浏览器显示广告的问题
- Instagram 开源用于 Python 3的MonkeyType 工具
- 拼凑了几个自定义的Panel(包括FishEyePanel,WrapPanel等几个常用的布局)
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 《hdu 免费馅饼》
- 技术分享 | 使用 pt-query-digest 分析慢日志
- 2019.8.15乘兴打Codeforces Round #569 (Div. 2)小记
- Codeforces Beta Round #14 (Div. 2)A. Letter
- Vue 改变数据,页面不刷新的问题
- R语言再保险合同定价案例研究
- 开发一个简单的 Vue 弹窗组件
- R语言模拟人类生活预期寿命动态可视化动画图gif
- Vue 动态添加路由及生成菜单
- R语言泊松回归对保险定价建模中的应用:风险敞口作为可能的解释变量
- Vue 页面权限控制和登陆验证
- Codeforces Round #502 (in memory of Leopoldo Taravilse, Div. 1 + Div. 2)C. The Phone Number
- Codeforces Beta Round #3 C. Tic-tac-toe
- [记录] 数据库中,根据经纬度,查询距离最近的地点
- PAT (Basic Level) Practice (中文)1010 一元多项式求导 (25 分)