异常处理进阶

异常处理进阶 (★★★)

#abap-objects #exception #raise-exception

概览表

项目 关键点
RAISE EXCEPTION 抛出类异常
异常传播 通过 RAISING 声明向上传播
创建异常类 全局/局部异常类
异常文本 OTR文本或消息类
异常映射 将一种异常映射为另一种

抛出异常

基本语法

1
2
3
RAISE EXCEPTION TYPE cx_sy_arithmetic_overflow
EXPORTING
textid = cx_sy_arithmetic_overflow=>division_by_zero.

带自定义属性

1
2
3
4
RAISE EXCEPTION TYPE zcx_validation_error
EXPORTING
message = 'Invalid input'
value = lv_input.

重新抛出

1
2
3
4
5
CATCH cx_root INTO DATA(lo_exc).
" 记录日志
WRITE: / lo_exc->get_text( ).
" 重新抛出原始异常
RAISE EXCEPTION lo_exc.

异常传播 (Propagation)

当方法不想处理异常时,可以将其传播给调用者:

1
2
3
4
5
6
7
8
CLASS lcl_calculator DEFINITION.
PUBLIC SECTION.
METHODS: divide
IMPORTING !iv_a TYPE i
!iv_b TYPE i
RETURNING VALUE(rv_result) TYPE decfloat16
RAISING cx_sy_arithmetic_overflow. " 声明传播
ENDCLASS.

传播规则

异常类型 是否需要RAISING 说明
CX_STATIC_CHECK 必须 编译器强制检查
CX_DYNAMIC_CHECK 不强制 但建议声明
CX_NO_CHECK 不需要 总是可以传播
💡RAISING 的作用
RAISING 声明是方法接口的一部分。它告诉调用者”这个方法可能抛出以下异常”,调用者必须处理或继续传播。

创建异常类

全局异常类

  1. Class Builder 中创建(前缀 ZCX_ 或 YCX_)
  2. 继承 CX_STATIC_CHECK(推荐默认)
  3. 定义属性(错误信息)
  4. 维护异常文本

异常文本

方式 说明
OTR文本 Object Text Repository,SAP标准方式
消息类 引用 T100 消息
内联文本 简单场景
1
2
3
4
5
6
" 使用消息类的异常
METHODS: constructor
IMPORTING
!textid LIKE if_t100_message=>t100key OPTIONAL
!previous TYPE REF TO cx_root OPTIONAL
!msgv1 TYPE sy-msgv1 OPTIONAL.

局部异常类

1
2
3
4
5
6
CLASS lcx_error DEFINITION INHERITING FROM cx_static_check.
PUBLIC SECTION.
DATA: mv_message TYPE string.
METHODS: constructor
IMPORTING !iv_message TYPE string.
ENDCLASS.

异常映射 (Exception Mapping)

将一种异常映射为另一种:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
METHODS: process_data
RAISING zcx_application_error.

METHOD process_data.
TRY.
" 调用可能抛出 CX_SY_ARITHMETIC_OVERFLOW 的方法
DATA(result) = calculate( ).

CATCH cx_sy_arithmetic_overflow INTO DATA(lo_exc).
" 映射为应用异常
RAISE EXCEPTION TYPE zcx_application_error
EXPORTING
previous = lo_exc " 保留原始异常
textid = zcx_application_error=>calculation_failed.
ENDTRY.
ENDMETHOD.

previous 参数

  • previous 参数保留原始异常链
  • 可以通过 lo_exc->previous 向上追溯
  • 实现异常的链式追踪

调试中的异常处理

  • 异常抛出时,调试器显示异常类名称
  • 如果被 CATCH 捕获,显示成功消息
  • 有两个按钮:分析异常对象、跳转到出错源码

考试/测试模式

场景/关键词 答案
“RAISING声明是必须的吗” CX_STATIC_CHECK必须
“previous参数的作用” 保留异常链,可追溯原始异常
“异常映射的目的” 将底层异常转换为应用层异常
“重新抛出异常” RAISE EXCEPTION lo_exc (不用 TYPE)
“CX_NO_CHECK传播规则” 不需要RAISING声明,总是传播