异常处理概念

异常处理概念 (★★★)

#abap-objects #exception #try-catch #cx-hierarchy

概览表

项目 关键点
类异常 基于类的异常处理,替代 sy-subrc
异常类层次 CX_ROOT → CX_STATIC_CHECK / CX_DYNAMIC_CHECK / CX_NO_CHECK
TRY结构 TRY ... CATCH ... CLEANUP ... ENDTRY
抛出异常 RAISE EXCEPTION TYPE cx_class

类异常概念

SAP Web AS 6.10 引入了基于类的异常处理:

  • 异常 = 异常对象 (Exception Object)
  • 异常对象 = 异常类的实例
  • 属性值包含错误信息
1
2
3
4
5
6
7
传统方式:                      类异常方式:
sy-subrc = 4. RAISE EXCEPTION TYPE cx_error.
IF sy-subrc <> 0. TRY.
" 处理错误 " 正常代码
ENDIF. CATCH cx_error INTO lo_exc.
" 处理异常
ENDTRY.
📌类异常不仅限于OO上下文
类异常可以在所有处理块中使用,包括过程式代码。所有可捕获的运行时错误也可以作为类异常处理。

异常类层次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
CX_ROOT (根异常类)
│ GET_TEXT( ) → 获取异常文本
│ GET_SOURCE_POSITION( ) → 获取出错位置

├── CX_NO_CHECK
│ " 不可声明检查 — 不需要在 RAISING 中声明
│ " 总是可以传播

├── CX_STATIC_CHECK (默认)
│ " 静态检查 — 必须在 RAISING 中声明或在 TRY 中处理
│ " 最严格,编译器检查
│ " 推荐默认使用

└── CX_DYNAMIC_CHECK
" 动态检查 — 运行时检查
" 不强制声明,但传播时检查
" 运行时错误属于此类

└── CX_SY_ARITHMETIC_ERROR
└── CX_SY_ARITHMETIC_OVERFLOW

三种异常类对比

类型 编译时检查 RAISING声明 适用场景
CX_STATIC_CHECK 必须 默认推荐
CX_DYNAMIC_CHECK 不强制 运行时错误
CX_NO_CHECK 不需要 资源短缺等不可避免的情况
⚠️不能直接继承 CX_ROOT
必须从 CX_NO_CHECKCX_DYNAMIC_CHECKCX_STATIC_CHECK 之一继承。

TRY-ENDTRY 控制结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
TRY.
" 可能抛出异常的代码
DATA(result) = 1 / 0.

CATCH cx_sy_arithmetic_overflow INTO DATA(lo_exc).
" 处理算术溢出
WRITE: / lo_exc->get_text( ).

CATCH cx_root INTO DATA(lo_root).
" 处理其他所有异常
WRITE: / lo_root->get_text( ).

CLEANUP.
" 当前TRY块没有匹配CATCH时的清理
" (异常被外层捕获时执行)

ENDTRY.

TRY块执行流程

1
2
3
4
5
6
7
1. 执行 TRY 块中的语句
2. 如果发生异常:
a. 从当前TRY块开始搜索匹配的 CATCH
b. 按 CATCH 顺序检查(匹配 = 异常类本身或其父类)
c. 找到 → 执行该 CATCH 块
d. 找不到 → 向外层 TRY 块扩展搜索
3. 如果没有匹配且没有外层 → 运行时错误
⚠️CATCH 的顺序
CATCH 按出现顺序检查。更具体的异常类应放在更通用的前面
如果先 CATCH cx_root,后面的 CATCH 永远不会执行。

分析异常对象

1
2
3
4
5
6
7
8
9
CATCH cx_sy_arithmetic_overflow INTO DATA(lo_exc).
" 获取异常文本
DATA(lv_text) = lo_exc->get_text( ).

" 获取出错位置
lo_exc->get_source_position(
IMPORTING
program_name = DATA(lv_prog)
line_number = DATA(lv_line) ).
💡INTO 的重要性
只有使用 INTO 时,系统才会实际创建异常对象。不用 INTO 时,为性能考虑不会创建。

异常类命名约定

范围 前缀 示例
系统预定义 CX_SY_ CX_SY_ARITHMETIC_OVERFLOW
全局异常类 CX_ (或 ZCX_) ZCX_VALIDATION_ERROR
局部异常类 LCX_ LCX_INVALID_INPUT

考试/测试模式

场景/关键词 答案
“CX_STATIC_CHECK vs CX_DYNAMIC_CHECK” STATIC必须声明/处理;DYNAMIC不强制
“CATCH顺序” 按出现顺序检查,具体类在前
“CLEANUP何时执行” 异常被外层或调用者捕获时
“CX_ROOT能直接继承吗” 不能,必须从三个子类之一继承
“INTO的作用” 创建异常对象引用以便分析
“get_text( )” 返回异常文本(来自IF_MESSAGE接口)