异常处理

基于类的异常exception classes 捕获

使用老式方式捕获catchable runtime errors

向上抛出异常

手动触发异常(类异常)

6.1版本以后,TRY…ENDTRY结构:

异常的触发:

函数异常的定义、抛出、与处理

Exception Handling

异常处理

基于类的异常是从6.10版本开始,它们是以异常类实例方式来实现。异常类是系统预先定义好的全局类或者是由用户自定义的局部或全局的类。

在sap6.10版本里,exception classes已经取代了catchable runtime errors

基于类的异常exception classes 捕获

DATA myref TYPE REF TO cx_sy_arithmetic_error.
DATA err_text TYPE string.
DATA result TYPE i.
TRY.
    result = 1 / 0.
CATCH cx_sy_arithmetic_error INTO myref.
    err_text = myref->get_text( ).
ENDTRY.
这个写法与java是相似的

使用老式方式捕获catchable runtime errors

catchable runtime errors

CATCH SYSTEM-EXCEPTIONS [exc1 = n1 exc2 = n2 ...] 
                                  [OTHERS = n_others].

  [statement_block]
ENDCATCH.

OTHERS接收所有前面异常列表 n1 n2 …未捕获到的异常。

DATA: result TYPE i.
CATCH SYSTEM-EXCEPTIONS arithmetic_errors = 5.
    result = 1 / 0.   
ENDCATCH.
IF sy-subrc = 5.
  WRITE / 'Division by zero!'.
ENDIF.

现一般不用这种方式了,而是这样:

DATA result TYPE p DECIMALS 2.
  DATA oref TYPE REF TO cx_root.
  DATA text TYPE string.
  DATA i TYPE i.

TRY .
      i = 1 / 0.
  CATCH cx_root INTO oref.
      text = oref->get_text( ).
      WRITE: '---' , text.
      RAISE EXCEPTION oref.”注:如果有此句,则不能放在Function中,否则报:Old and class-based exceptions must not be used the same time
  ENDTRY.

向上抛出异常

如果Form中出现了运行时错误,但Form签名又没有使用RAISING向上抛,则程序会直接挂掉,所以最好是向上抛

FORM subform RAISING cx_static_check cx_dynamic_check.
...

ENDFORM.

Funcion函数不会主动向外抛出运行时错误,所以要先在Function手动CATCH,再手动向外抛,如果出现运行时错误不抛出,则Function与会直接宕掉:

手动触发异常(类异常)

RAISE EXCEPTION { {TYPE cx_class [EXPORTING p1 = a1 p2 = a2 ...]}
                | oref }.

EXPORTING选项表示的是异常类构造函数的参数。

DATA: exc  TYPE REF TO cx_sy_dynamic_osql_semantics,
      text TYPE string.
TRY.
  RAISE EXCEPTION TYPE cx_sy_dynamic_osql_semantics
                     EXPORTING textid = cx_sy_dynamic_osql_semantics=>unknown_table_name token  = 'Test'.
  CATCH cx_sy_dynamic_osql_semantics INTO exc.
    text = exc->get_text( ).
    MESSAGE text TYPE 'I'.
ENDTRY.

6.1版本以后,TRY…ENDTRY结构:

TRY.
    [try_block]
CATCH cx_class1 cx_class2 ... [INTO oref].
    [catch_block]
    ...
[CLEANUP [INTO oref].
    [cleanup_block]]
ENDTRY.

CLEARUP是在所在的TRY CATCH发生了异常,但在本TRY CATCH中无法捕获,异常再次向上递交给上层TRY CATCH前被执行的,它不同于Java中的finally

PARAMETERS number TYPE i.
DATA result TYPE p DECIMALS 2.
DATA oref TYPE REF TO cx_root.
DATA text TYPE string.
START-OF-SELECTION.
  TRY.
      IF ABS( number ) > 100.
        RAISE EXCEPTION TYPE cx_demo_abs_too_large.
      ENDIF.
      TRY.
          result = 1 / number.
          WRITE: / 'Result of division:', result.
          result = SQRT( number ).
          WRITE: / 'Result of square root:', result.
        CATCH cx_sy_zerodivide INTO oref."输出0时会在这里捕获
          text = oref->get_text( ).
          CONCATENATE 'CATCH cx_sy_zerodivide : ' text INTO text.
        CLEANUP."当内层TRY发生了异常,且没有被捕获到,抛到外层TRY前会被执行
          CLEAR result.
          WRITE: / 'cleanup'.
      ENDTRY.
    CATCH cx_sy_arithmetic_error INTO oref."输入负数会在这里捕获
      text = oref->get_text( ).
      CONCATENATE 'CATCH cx_sy_arithmetic_error : ' text INTO text.
    CATCH cx_root INTO oref."输入的数大于100时会在这里捕获
      text = oref->get_text( ).
       CONCATENATE 'CATCH cx_root : ' text INTO text.
  ENDTRY.

IF NOT text IS INITIAL.
    WRITE / text.
  ENDIF.
  WRITE: / 'Final result:', result.

 

异常的触发:

l  运行出错时,系统会自动触发预定好的异常类(类似于Java中的运行时异常,6.10前是触发的预定好的错误)

l  可以使用RAISE EXCEPTION手动触发异常(类似Java的throw)

l  对于局部的类的METHODS、过程FORM后加上RAISING 选项来声明要抛出的异常,向上继续抛出(类似Java的throws),全局的函数异常在Exceptions标签里如下设置:

在代码中手动直接抛出异常即可:

l  类的静态构造函数不能抛出异常

l  event handler定义时不能抛出异常

l  使用SUBMIT ... AND RETURN 或者CALL TRANSACTION调用程序时,不能将异常传播给调用者,因为异常对象是与程序的内部会话绑定的

三类异常:

l  CX_STATIC_CHECK

l  CX_DYNAMIC_CHECK

l  CX_NO_CHECK

具体的异常类继承结构请查看SAP帮助,输入“EXCEPTION”

类比:CX_NO_CHECK类似于Java中的Error,CX_DYNAMIC_CHECK类似于Java中的RuntimeException,CX_STATIC_CHECK类似于Java检测性异常

CX_STATIC_CHECK是一个抽象类,一般自己定的异常都要求继承于它。在程序中使用RAISE EXCEPTION 手动抛出这类异常时,方法或过程接口上一定要显示的通过RAISING 来向上层抛出异常(或者直接在方法或过程中进行处理也可以),否则静态编译时就会出现警告。

CX_NO_CHECK类型的异常一般表示系统资源不足引起的,不能在方法或过程接口后面抛出CX_NO_CHECK类型的异常,它会被隐含的抛出与传递。系统中已有预定义这类异常。

如果程序逻辑能够排除可能性的潜在性错,相应的异常就可能不用处理或继续抛出,此类情况下可以使用CX_DYNAMIC_CHECK类型的异常,这与Java中的运行时异常相似,一旦发生也该类异常,表示问题出现在程序的本身设计上,程序设计不严谨(如没有判断空指针问题)。ABAP大多数的系统预定义的异类都是属于该类型异常,这就意味着不需要处理或抛出ABAP语句可能出现的每一种异常,但一旦发生了该类异常,则表示程序的逻辑出现了问题,程序执行的结果将不会在正确。

异常类可以被定义成全局的类或者是局部的异常类,全局异常类名称以CX_, YCX_, ZCX_为前缀。系统里预定义好的全局异常类都是能CX_SY_为前缀来命名的。

如果是通过Class Builder创建的全局异常类时,由于构造器是默认创建好的,不能传递参数,所以异常文本ID只能通过TEXTID传递,但局部异常类没有这个限制。

如果在抛出的异常类在构造的过程中(构造函数中)发生了异常,则会使用CX_SY_NO_HANDLER异常来代替原来的异常实例。

函数异常的定义、抛出、与处理

CALLFUNCTION时一定不能省略Exceptions选项(EXCEPTIONS表示函数接口需要抛出异常,如果函数里抛出了异常,但调用时接口上没有加上该选项,则程序运行时会中断),否则异常不能捕获,运行时会出错。其实Exception先项就相当于TRY ... CATCH...

Exception Handling

关于异常更多详情,请参考SAP 帮助Exception Handling

原文出自 江正军 技术博客,博客链接:www.cnblogs.com/jiangzhengjun

ABAP-异常捕获的更多相关文章

  1. .NET 基础 一步步 一幕幕[数组、集合、异常捕获]

    数组.集合.异常捕获 数组: 一次性存储多个相同类型的变量. 一维数组: 语法: 数组类型[] 数组名=new 数组类型[数组长度]; 声明数组的语法: A.数据类型 [] 数组名称= new 数据类 ...

  2. MVC 好记星不如烂笔头之 ---> 全局异常捕获以及ACTION捕获

    public class BaseController : Controller { /// <summary> /// Called after the action method is ...

  3. atitit.js浏览器环境下的全局异常捕获

    atitit.js浏览器环境下的全局异常捕获 window.onerror = function(errorMessage, scriptURI, lineNumber) { var s= JSON. ...

  4. C#中的那些全局异常捕获

    1.WPF全局捕获异常     public partial class App : Application     {         public App()         {    // 在异 ...

  5. Spring-MVC开发之全局异常捕获全面解读

    异常,异常 我们一定要捕获一切该死的异常,宁可错杀一千也不能放过一个! 产品上线后的异常更要命,一定要屏蔽错误内容,以免暴露敏感信息! 在用Spring MVC开发WEB应用时捕获全局异常的方法基本有 ...

  6. JavaScript异常捕获

    理论准备 ★   异常捕获 △ 异常:当JavaScript引擎执行JavaScript代码时,发生了错误,导致程序停止运行: △ 异常抛出:当异常产生,并且这个异常生成一个错误信息: △ 异常捕获: ...

  7. SQLServer异常捕获

    在SQLserver数据库中,如果有很多存储过程的时候,我们会使用动态SQL进行存储过程调用存储过程,这时候,很可能在某个环节就出错了,但是出错了我们很难去跟踪到出错的存储过程,此时我们就可以使用异常 ...

  8. Asp.Net MVC3(三)-MvcApp实现全局异常捕获

    定义异常捕获类: [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMu ...

  9. iphone 异常捕获处理

    iphone 异常捕获处理 1 void UncaughtExceptionHandler(NSException *exception) { 2 NSArray *arr = [exception ...

  10. iOS异常捕获

    文章目录 一. 系统Crash 二. 处理signal 下面是一些信号说明 关键点注意 三. 实战 四. Crash Callstack分析 – 进⼀一步分析 五. demo地址 六. 参考文献 前言 ...

随机推荐

  1. 使用Apache Mesos和Consul实现服务的注册发现

    为保证基于Docker应用程序和服务都具有高性能和可用性,设计出一种具有服务发现,高可用性和容错能力的解决方案非常重要. 我们使用Apache Mesos 和Mesosphere的 Marathon实 ...

  2. MySQL学习----索引的使用

    一.什么是索引?为什么要建立索引? 索引用于快速找出在某个列中有一特定值的行,不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大,查询数据所花费的时间就越多,如果表中查询的 ...

  3. VLAN原理

    体系结构(分层次): 更好的细化结构,能够更清楚的分析数据在整个转发过程中的变化过程.尽可能的把功能独立分开,放到不同层次上. 物理上的拓扑结构:总线型/环形/星形 逻辑上的拓扑:星形总线 OSI七层 ...

  4. Jmeter(五)录制功能

    难得休息时间,和开发对完需求便理着Jmeter的知识的相关体系,趁闲暇功夫就记一点,希望这么坚持下去,能有很多关于Jmeter的知识点被总结,被挖掘出来,从而形成自己的一套知识体系..... 嗯,那本 ...

  5. [UE4]不精准射击 Random Unit Vector in Cone in Radians

  6. Round544div3E(1133E)

    一.题目链接 https://codeforces.com/problemset/problem/1133/E 二.思路 显然要使用dp,因为中间有部分人不会选取. 令$dp[i][j]$表示在前$i ...

  7. 【LeetCode】3. 无重复字符的最长子串

    给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc&qu ...

  8. Java - 14 Java 日期时间

    java.util包提供了Date类来封装当前的日期和时间. Date类提供两个构造函数来实例化Date对象. 第一个构造函数使用当前日期和时间来初始化对象. Date( ) 第二个构造函数接收一个参 ...

  9. 《linux性能及调优指南》 3.3 内存瓶颈

    摘要:3.3内存瓶颈OnaLinuxsystem,manyprogramsrunatthesametime.Theseprogramssupportmultipleusers,andsomeproce ...

  10. Android模块化开发、组件化开发;

    模块化开发:优点嘛,项目过大时便于管理: 1.在根目录的gradle.properties文件下添加 isBuildModule=false: 使用isBuildModule来控制这个是Library ...