写点什么

ABAP 一组关键字 IS BOUND, IS NOT INITIAL 和 IS ASSIGNED 的用法辨析

作者:Jerry Wang
  • 2022 年 8 月 19 日
    四川
  • 本文字数:1890 字

    阅读完需:约 6 分钟

ABAP 一组关键字 IS BOUND, IS NOT INITIAL 和 IS ASSIGNED 的用法辨析

ABAP 里的 IS BOUND, IS NOT INITIAL 和 IS ASSIGNED 这组关键字,如果平时不留心,很容易理解地似是而非。今天我们就来说一说它们的区别。


先把 SAP 帮助文档抄过来:


IS BOUND


It checks whether a reference variable contains a valid reference. A data reference variable that contains a stack reference, on the other hand, can become invalid even if the reference data object is removed from the stack.


IS INITIALchecks whether the operand operand is initial. The expression is true, if the operand contains its type-friendly initial value.


IS ASSIGNEDchecks whether a memory area is assigned to a field symbol. The expression is true if the field symbol points to a memory area.


简单翻译成中文:


IS BOUND:用于检查一个引用变量是否指向了一个有效的引用。帮助文档特意提到,如果一个引用指向的是一个栈上申请的变量,那么这个变量会随栈的销毁而被销毁,因此指向其的引用不再有效。


IS INITIAL: 用于检查一个变量的值是否为其数据类型对应的初始值。


比如我定义一个引用变量但不对其赋值,则 IS INITIAL 判断一定为 abap_true.



IS ASSIGNED: 对于检测的 field symbol,该关键字判断该 field symbol 是否分配有内存区域。


这三个关键字交织在一起,就形成了一些有趣的排列组合。


比如,是否存在 NOT INITIAL, 但同时也 NOT BOUND 的变量?是否存在同时满足 IS INITIAL, NOT BOUND 和 IS ASSIGNED 的 field symbol? 下面我们用一个简单的 ABAP 报表来研究这些排列组合。


完整的测试代码:



同时满足 NOT INITIAL 和 NOT BOUND 的引用变量


下图 main 方法里,第 15 行在栈上定义了一个整型变量 number,将其引用赋给类的成员变量 dref. 待 main 方法执行之后,number 所生存的栈帧被销毁,因此 dref 指向的引用不再有效,调试器里显示为:FREED STACK.



现在 dref 并不是未指向任何引用,而是指向一个无效的引用,因此 dref 同时满足 IS NOT INITIAL 和 IS NOT BOUND.


IS ASSIGNED


一个 field symbol 定义之后,如果不为其分配内存区域,则 IS ASSIGNED 返回 abap_false.


下面的代码,如果注释掉第 27 行的 IF 条件:



运行时会抛出 GETWA_NOT_ASSIGNED 错误:Field symbol has not yet been assigned.



也就是说,无论是读取 field symbol 具体的内容,还是检测其内容是否为初始值,为了避免 GETWA_NOT_ASSIGNED 错误,我们必须在 IS INITIAL 判断之前,使用 IS ASSIGNED 判断 field symbol 是否被分配了内存区域。


是否存在一个 NOT BOUND, IS INITIAL 但是却 IS ASSIGNED 的 field symbol?


答案是肯定的。



上面代码第 37 行定义的名为<any2>的 field symbol,在第 45 行的 CLEAR 操作完成之后,就同时满足这三个条件。这个 field symbol 被分配的内存区域,内容并不是整型数本身,而是一个指向整型变量的引用。


该报表打印输出如下:



第 40 行代码通过 ASSIGN 分配给<any2>的内存区域并未通过 UNASSIGN 释放,因此<any2> IS ASSIGNED 始终返回 abap_true. 另一方面,这块内存区域虽然还未释放,但里面存放的引用变量已经不再指向任何一个有效的变量了,因此 IS BOUND 返回 abap_false. 最后,因为<any2>施加了 CLEAR 操作, 又回到了初始化状态,所以 IS INITIAL 返回 abap_true.



一句话总结,就是:判断引用变量是否有效,用 IS BOUND; 判断变量是否处于初始状态,用 IS INITIAL; 判断 field symbol 是否分配有内存区域,用 IS ASSIGNED. 在对 field symbol 进行各种操作之前,先调用 IS ASSIGNED 进行判断,以避免 GETWA_NOT_ASSIGNED 错误。


假设我有这个 JSON 字符串如下图所示:



我的任务是解析出上图黑色方框里的几个字段,比如 ObjectID, ETag, BuyerID, DateTime, ID, Name 等等,把它们的值存储到对应 ABAP 变量里。


下面是 ABAP 解析方案。


  1. 首先定义一个 ABAP 结构,包含需要解析的几个字段。


TYPES: BEGIN OF ty_header,objectid TYPE string,buyerid  TYPE string,datetime TYPE string,id       TYPE string,name     TYPE string,END OF ty_header.
复制代码


然后定义一个 ABAP 结构,字段名为 results,对应本文截图里加了红色下划线的 json 字符串中的 results 字段,类型为刚刚定义的 ty_header:


TYPES: BEGIN OF ty_result,results TYPE ty_header,END OF ty_result.
复制代码


同样,再定义一个 ABAP 结构 ty_d:


TYPES: BEGIN OF ty_d,d TYPE ty_result,END OF ty_d.


总之,ABAP 里定义的结构,其字段名和层次结构必须和 JSON 字符串一致。


  1. 定义一个 ABAP 变量用于存储反序列化结果,类型为步骤一的 ty_d:


DATA: ls_data TYPE ty_d.
WRITE:/ lv_response.
CALL METHOD /ui2/cl_json=>deserializeEXPORTINGjson = lv_responseCHANGINGdata = ls_data.
复制代码


执行上述代码,发现反序列化成功:





感谢阅读。

发布于: 2022 年 08 月 19 日阅读数: 20
用户头像

Jerry Wang

关注

🏆InfoQ写作平台-签约作者🏆 2017.12.03 加入

SAP成都研究院开发专家,SAP社区导师,SAP中国技术大使。2007 年从电子科技大学计算机专业硕士毕业后加入 SAP 成都研究院工作至今。工作中使用 ABAP, Java, JavaScript 和 TypeScript 进行开发。

评论

发布
暂无评论
ABAP 一组关键字 IS BOUND, IS NOT INITIAL 和 IS ASSIGNED 的用法辨析_指针_Jerry Wang_InfoQ写作社区