ABAP基础知识 类的例外处理

前言

在类方法中处理业务逻辑时,对于异常情况需要中断类定义或者类方法的执行.同时这些异常情况还需要被调用点捕获,以便报错或者进入例外处理逻辑.

如果没有捕获这些错误,则会产生SHORT DUMP.

本文主要讲解类中触发异常的方式及调用类捕获异常的方式

异常处理方式

在ABAP类中异常处理有两种方式

  • 传统方式

  • 异常类方式

这两种方式不能混用. 一个特定的类方法中只能使用一种方式.但是同一个类中的不同的方法可以各自使用一种方式

传统方式

传统方式与函数的异常处理类似.

01

触发异常

在类方法中添加异常, 通过RAISE 语句或者 MESSAGE   RAISING  触发异常.

19abc85d9ed1e19501cc0faeaf3e43e6.png

027ef5b6cc383e476579dba3dc09e8a8.png

02

捕获异常

传统异常的捕获只能通过 调用方法时,传递EXCEPTION 参数. 特定异常返回一个值到 SY-SUBRC 中. 在调用点对 SY-SUBRC 内容进行判断,执行后续逻辑.

4238dcee08265f9130c9576bc27a549a.png

3051c178b412b8cba277187f76048203.png

异常类方式

使用一个特殊的类-异常类来集中管理异常

01

创建异常类

创建一个异常类ZCX_TEST_EXCEPTION,创建的时候,系统识别ZCX_前缀, 会自动填充超类 CX_STATIC_CHECK ,且类型设置为异常类.异常类会自动生成类的构造方法代码且不可修改.

62927e47e65029e1fc2e94e28e0ca839.png

02

可能犯的错误

如果异常类的实例生成没有设置为2. 使用时会报下图的错误, 设置成公用后, 就不会报错了.

dd6d2f81f37cff310b801c7d9cefc77c.png

如果在类方法的异常中没有引入异常类, 语法检查报警告,捕获错误没有明确的信息

1b43f18db530e867c35add821e80fcd1.png

测试调用对象,捕获如下错误

1a5c3bd6e391a7e950922228ccdfc39b.png

03

引入异常类

需要在例外中引用该异常类

cc701401fabe890a23dfd8cc6ece3071.png

04

触发异常类

触发异常时可以传递参数, 也可以不传递参数,使用异常类中默认的消息

f675c3942cdc0d5aea23e114a0e05a90.png

05

异常类的捕获

15106879ecc1ecfcf7a7b673218fb7b8.png

df3fa0118a8cabe36aab396e5b256c31.png

06

触发异常类传递的参数

MSGID  MSGNO 用于识别一条消息. ATTR1-ATTR4 传递的并不是消息的变量内容. 而是类的属性 . 比如 IF_T100_DYN_MSG~MSGV1 或者自定义的属性

如果在ATTR1-ATTR4中传递一个字符串. 最终捕获的错误文本中 将出现 &字符串&

异常类中需要定义属性默认值. 这样才能通过参数传递所需的属性的名称. 最终使用消息+属性内容形成消息内容

83f979439b7058def8c5e4de048910a9.png

6add62dc0df8ff7b2fe6e277e0e99fb3.png

通用异常类

如果希望系统生成的异常类传递错误消息内容不带&符号.可以通过添加异常类属性和改写 IF_MESSAGE~GET_TEXT 方法. 在RAISE EXCEPTION时传递一个消息描述

01

创建异常类

创建一个通用异常类 ZCX_BC_COMM

5b0fa094c23370142a43065f6c048bf9.png

02

添加属性

添加属性 ERROR_TEXT

添加的属性会自动出现在构造方法中的参数中,并且会自动添加赋值到属性的语句

8d657ac344fca02f5e1b8eaa6f56ab04.png

03

重定义方法

重定义方法 IF_MESSAGE~GET_TEXT

eceada4dd1ad88e6b7cad5e7f577a343.png

重定义方法的代码内容 优先获取 me->error_text 属性中的内容返回

bcc12c6b1f621857f7e3df597edb1c27.png

04

触发通用异常类

触发异常类时,传递自定义的属性生成的参数

2bf5f842fc78df2f89e194eb743c57a0.png

05

捕获的消息

403270c7ea315044ef67c47533028570.png

208a7377dba53eaa89ac3074a797541c.png

总结

类异常的触发及捕获建议使用异常类的方式. 这样可以更加灵活的处理类异常情况.

捕获异常时,可以使用特定的异常类捕获. 也可以使用根类 CX_ROOT捕获(在不知道特定的异常类的情况下)

本文涉及到的代码

  • 测试程序        ZTS_CLASS_EXCEPTION

  • 对应的测试类 ZCL_TEST_EXCEPTION

  • 对应的异常类 ZCX_TEST_EXCEPTION

  • 通用异常类     ZCX_BC_COMM

详细代码详见文末(异常类系统不支持源码显示模式,无法复制源代码)

约定

如果你对这篇文章感兴趣,请帮忙点赞,在看,分享.       

    (如果你真的喜欢这篇文章,请记得回来打个赏,作为支持我继续下去的动力,这是一个正反馈过程. 越多的人打赏,作者越有动力分享,读者就能享受更多的福利.毕竟打赏的金额富不了我,穷不了你,却能支持这个公众号长久发文.)

afdb99055f60a34456e2148eb2582d5d.png

公众号 : syjf1976_abap

          ABAP开发技巧

微信号 : 392077

请微信联系管理员: 

syjf1976 

sharry_xlp  

Yannick_Duan 

申请进入公众号讨论群提问或者参与话题讨论

源代码部分

ZTS_CLASS_EXCEPTION

*&---------------------------------------------------------------------*
*& Report ZTS_CLASS_EXCEPTION
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zts_class_exception.


DATA: gc_test TYPE REF TO zcl_test_exception.


START-OF-SELECTION.
*创建对象
  CREATE OBJECT gc_test.
  cl_demo_output=>next_section( title = '返回例外:' ).
*使用旧的例外方式: 单行代码
  CALL METHOD gc_test->test_old( EXPORTING iv_error = '1' EXCEPTIONS error_1 = 1 error_2 = 2 ).
  IF sy-subrc <> 0.
    cl_demo_output=>write( '类方法返回例外:' && sy-subrc && '无消息' ).
  ENDIF.
*使用旧的例外方式:多行代码
  CALL METHOD gc_test->test_old
    EXPORTING
      iv_error = '2'
    EXCEPTIONS
      error_1  = 1
      error_2  = 2
      OTHERS   = 3.
  IF sy-subrc <> 0.
    cl_demo_output=>write( '类方法返回例外:' && sy-subrc && '成功消息:' && sy-msgno && sy-msgty && sy-msgid && sy-msgv1 ).
  ENDIF.


*使用旧的例外方式:新语法创建对象并调用方法.
  NEW zcl_test_exception( )->test_old( EXPORTING iv_error = '3' EXCEPTIONS error_1 = 1 error_2 = 2 error_3 = 3 ) .
  IF sy-subrc <> 0.
    cl_demo_output=>write( '类方法返回例外:' && sy-subrc && '错误消息:'  && sy-msgno && sy-msgty && sy-msgid && sy-msgv1 ).
  ENDIF.


*使用新的例外方法
  cl_demo_output=>next_section( title = '捕获例外,错误方式:' ).
  TRY.
      CALL METHOD gc_test->test_new( EXPORTING iv_error = '1' ).
    CATCH cx_root INTO DATA(lo_ref).    "也可以捕获这个所有错误类的根类
      DATA(lv_msg) = lo_ref->get_text( ).
      cl_demo_output=>write( '捕获类中的例外:' && lv_msg ).
  ENDTRY.
*带有消息的例外.
  TRY.
      CALL METHOD gc_test->test_new( EXPORTING iv_error = '2' ).
    CATCH cx_root INTO lo_ref.    "也可以捕获这个所有错误类的根类
      lv_msg = lo_ref->get_text( ).
      cl_demo_output=>write( '捕获类中的例外:' && lv_msg ).
  ENDTRY.


*使用新的例外方法
  cl_demo_output=>next_section( title = '捕获例外,正确方式:' ).
  TRY.
      CALL METHOD gc_test->test_new_right( EXPORTING iv_error = '1' ).
    CATCH zcx_test_exception INTO lo_ref.    "可以捕获特定的异常类
      lv_msg = lo_ref->get_text( ).
      cl_demo_output=>write( '捕获类中的例外:' && lv_msg ).
  ENDTRY.
*带有消息的例外.
  TRY.
      CALL METHOD gc_test->test_new_right( EXPORTING iv_error = '2' ).
    CATCH cx_root INTO DATA(lo_ref_root).    "也可以捕获这个所有错误类的根类
      lv_msg = lo_ref_root->get_text( ).
      cl_demo_output=>write( '捕获类中的例外:' && lv_msg ).
  ENDTRY.




*使用通用异常类
  cl_demo_output=>next_section( title = '捕获例外,正确方式(通用异常类ZCX_BC_COMM):' ).
  TRY.
      CALL METHOD gc_test->test_comm( EXPORTING iv_error = '1' ).
    CATCH zcx_bc_comm INTO DATA(lo_ref_comm).    "可以捕获特定的异常类
      lv_msg = lo_ref_comm->get_text( ).
      cl_demo_output=>write( '捕获类中的例外:' && lv_msg ).
  ENDTRY.
*带有消息的例外.
  TRY.
      CALL METHOD gc_test->test_comm( EXPORTING iv_error = '2' ).
    CATCH cx_root INTO DATA(lo_ref_comm_root).    "也可以捕获这个所有异常类的根类
      lv_msg = lo_ref_comm_root->get_text( ).
      cl_demo_output=>write( '捕获类中的例外:' && lv_msg ).
  ENDTRY.
  cl_demo_output=>display( ).

ZCL_TEST_EXCEPTION

class ZCL_TEST_EXCEPTION definition
  public
  final
  create public .


public section.


  methods CONSTRUCTOR .
  methods TEST_OLD
    importing
      !IV_ERROR type CLIKE
    exceptions
      ERROR_1
      ERROR_2
      ERROR_3 .
  methods TEST_NEW
    importing
      !IV_ERROR type CLIKE .
  methods TEST_NEW_RIGHT
    importing
      !IV_ERROR type CLIKE
    raising
      ZCX_TEST_EXCEPTION .
  methods TEST_COMM
    importing
      !IV_ERROR type CLIKE
    raising
      ZCX_BC_COMM .
protected section.
private section.
ENDCLASS.






CLASS ZCL_TEST_EXCEPTION IMPLEMENTATION.




* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_TEST_EXCEPTION->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* +--------------------------------------------------------------------------------------</SIGNATURE>
  method CONSTRUCTOR.
  endmethod.




* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_TEST_EXCEPTION->TEST_COMM
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_ERROR                       TYPE        CLIKE
* | [!CX!] ZCX_BC_COMM
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD test_comm.
    CASE iv_error.
      WHEN '1'. "测试文本
        DATA:lv_str TYPE string.
        lv_str = '测试文本消息内容'.
        RAISE EXCEPTION TYPE zcx_bc_comm
          EXPORTING
            error_text = lv_str.


      WHEN '2'. "测试消息
        DATA: ls_syst TYPE syst.
        ls_syst-msgty = 'E'.
        ls_syst-msgid = '00'.
        ls_syst-msgno = '001'.
        ls_syst-msgv1 = '测试SYST消息'.
        RAISE EXCEPTION TYPE zcx_bc_comm
          EXPORTING
            syst_at_raise = ls_syst.
    ENDCASE.
  ENDMETHOD.




* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_TEST_EXCEPTION->TEST_NEW
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_ERROR                       TYPE        CLIKE
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD test_new.
    DATA: lv_textid TYPE scx_t100key.
    CASE iv_error.
      WHEN '1'.
        RAISE EXCEPTION TYPE zcx_test_exception.
      WHEN '2'.
        lv_textid-msgid = '00'.
        lv_textid-msgno = '001'.
        lv_textid-attr1 = '测试异常类消息'.
*        LV_TEXTID-ATTR2
*        LV_TEXTID-ATTR3
*        LV_TEXTID-ATTR4
        RAISE EXCEPTION TYPE zcx_test_exception
          EXPORTING
            textid = lv_textid
*           previous =
          .
    ENDCASE.
  ENDMETHOD.




* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_TEST_EXCEPTION->TEST_NEW_RIGHT
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_ERROR                       TYPE        CLIKE
* | [!CX!] ZCX_TEST_EXCEPTION
* +--------------------------------------------------------------------------------------</SIGNATURE>
  METHOD test_new_right.
    DATA: lv_textid TYPE scx_t100key.
    CASE iv_error.
      WHEN '1'.
        RAISE EXCEPTION TYPE zcx_test_exception.
      WHEN '2'.
        lv_textid-msgid = '00'.
        lv_textid-msgno = '001'.
        lv_textid-attr1 = 'IF_T100_DYN_MSG~MSGV1'. "ATTR1放异常类的属性.
        lv_textid-attr2 = '/把文本放入属性'. "文本放入属性, 最终显示的文本会前后添加 &符号
*        lv_textid-attr3 = '3'.
*        lv_textid-attr4 = '4'.
        RAISE EXCEPTION TYPE zcx_test_exception
          EXPORTING
            textid = lv_textid
*           previous =
          .


    ENDCASE.
  ENDMETHOD.




* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_TEST_EXCEPTION->TEST_OLD
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_ERROR                       TYPE        CLIKE
* | [EXC!] ERROR_1
* | [EXC!] ERROR_2
* | [EXC!] ERROR_3
* +--------------------------------------------------------------------------------------</SIGNATURE>
  method TEST_OLD.
    CASE IV_ERROR.
      WHEN '1'.
        RAISE ERROR_1.
      WHEN '2'.
        MESSAGE S001(00) WITH '测试消息S' RAISING ERROR_2.
      WHEN '3'.
        MESSAGE E001(00) WITH '测试消息E' RAISING ERROR_3. "与函数一致, 错误消息只会触发异常.不会终止类执行
    ENDCASE.
  endmethod.
ENDCLASS.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值