美文网首页想法简友广场SAP
ABAP基础知识 类的例外处理

ABAP基础知识 类的例外处理

作者: syjf1976_abap | 来源:发表于2021-10-28 11:06 被阅读0次

前言

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

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

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

异常处理方式

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

  • 传统方式

  • 异常类方式

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

    传统方式

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

    01

    触发异常

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

    02

    捕获异常

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

    异常类方式

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

    01

    创建异常类

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

    02

    可能犯的错误

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

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

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

    03

    引入异常类

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

    04

    触发异常类

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

    05

    异常类的捕获

    06

    触发异常类传递的参数

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

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

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

    通用异常类

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

    01

    创建异常类

    创建一个通用异常类 ZCX_BC_COMM

    02

    添加属性

    添加属性 ERROR_TEXT

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

    03

    重定义方法

    重定义方法 IF_MESSAGE~GET_TEXT

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

    04

    触发通用异常类

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

    05

    捕获的消息

    总结

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

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

    本文涉及到的代码

  • 测试程序        ZTS_CLASS_EXCEPTION

  • 对应的测试类 ZCL_TEST_EXCEPTION

  • 对应的异常类 ZCX_TEST_EXCEPTION

  • 通用异常类    ZCX_BC_COMM

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

    约定

    *&---------------------------------------------------------------------**& 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.

    相关文章

    网友评论

      本文标题:ABAP基础知识 类的例外处理

      本文链接:https://www.haomeiwen.com/subject/gsxvaltx.html