定义引用变量Reference Variables
引用变量存储的是某个对象的地址,而不是实际的内容。ABAP中的引用包括数据引用与对象引用,因此,ABAP中有数据引用变量与对象引用变量两种,而对象引用又分为类引用与接口引用。
数据引用使用CREATE DATA...创建数据对象,对象引用使用CREATE OBJECT...创建类对象,但定义都使用DATA ... TYPE REF TO...的方式来声明一个引用变量(指针)。
数据引用就是指对非对象如基本变量、结构体、内表变量的引用(类似C中的指针)。对象引用指的是对象ABAP语言中的对象进行引用(类似Java中的指针)。
创建数据引用变量的数据类型:
TYPES <t_dref> TYPE REF TO DATA.
使用上面创建出来的引用变量数据类型或者是直接通过下面的语句来创建数据引用变量:
DATA <dref> TYPE REF TO DATA.
DATA数据类型为通用类型,这里还可以使用其他通用类型或具体的类型。
动态创建数据对象Creating Data Objects Dynamically
以前在程序的声明部分通过DATA语句定义都是静态的数据对象,它们在程序运行前就已经存在了。如果想在程序运行期间动态的创建数据对象,则需要使用数据引用变量来动态的创建:
CREATE DATA <dref> TYPE <type>|LIKE <obj>.
该语句创建出一个数据对象,并使用 dref 指向它。与C中的指针一样,如果要访问该对象内容,则一定先要进行解引操作。注意:<dref>一定要先通过上面DATA...TYPE REF TO ... 语句定义过数据引用变量,这里只是创建与分配。另外,type还可以是动态指定的:
CREATE DATA <dref> TYPE (<name>).
.
DATA: dref TYPE REF TO typ.
"类型可以是动态指定
CREATE DATA dref TYPE ('TYP') .
dref->* = 'A'.
WRITE: / dref->*."A
TYPES : typ2 TYPE REF TO typ.
DATA: dref2 TYPE REF TO typ2."指向指针的指针
CREATE DATA dref2 .
DATA: dref3 TYPE REF TO typ2.
dref3 = dref2."指向同一东西
DATA: c VALUE 'A'.
GET REFERENCE OF c INTO dref2->*.
WRITE: / dref3->*->*."A
,line TYPE LINE OF tabtyp.
DATA: wa TYPE LINE OF tabtyp.
DATA: dref TYPE REF TO tabtyp.
CREATE DATA dref LIKE TABLE OF wa."注:TABLE OF 后面接的是内表的行类型
"CREATE DATA dref TYPE TABLE OF i."也可以是这样
"CREATE DATA dref TYPE TABLE OF line."也可以是这样
APPEND 1 TO dref->*.
LOOP AT dref->* INTO wa.
WRITE: wa.
ENDLOOP.
获取数据对象引用Getting References to Data Objects
将已存在的某数据对象分配给已定义好的数据引用变量:
GET REFERENCE OF <obj> INTO <dref>.
注意:<dref>一定要先通过上面DATA...TYPE REF TO ... 语句定义过数据引用变量,这里只是获取与分配。这里的数据对象obj 可以是通过DATA定义的数据对象(如基本内置数据类型变量),也可以是某字段符号,或者甚至还可以是DATA ... TYPE REF TO...定义的引用变量(此时相当于二级指针,请参考下面示例):
DATA dref TYPE REF TO string."第一步:定义
DATA dref2 TYPE REF TO DATA.
field-SYMBOLS <fs>.
field-SYMBOLS <fs1>.
field-SYMBOLS <fs2>.
CREATE DATA dref TYPE ('STRING')."第二步:创建
"因为定义时已经明确指定了数据类型,所以可以省略TYPE选项
*CREATE DATA dref.
ASSIGN dref->* to <fs2>."第三步:使用
<fs2> = 'ABCD'.
"dref2相当于二级指针
GET REFERENCE OF dref INTO dref2.
"要区分与上面的区别,下面这样直接赋值属于指针拷贝,
"结果是dref2与dref同指向同一个数据对象,此情况下的dref2则不是二级指针了
*dref2 = dref.
ASSIGN dref2->* to <fs>."第一次解引用
ASSIGN <fs>->* to <fs1>."第二次解引用
WRITE : / <fs1>.
ABCD
注意:不要将局部对象的引用传到其他过程中或不要引用局部对象,否则会出Java中不安全发布问题
可以将一个常量的地址分配给字段符号,但不能修改该常量的值:
DATA: e_i3 TYPE REF TO i .
.
以上代码运行时会报错。
或者直接获取某个非引用变量的地址:
.
WRITE: i.
解引用Dereferencing Data References
要访问数据引用(对象引用不需要)所指向的数据对象的内容,先一定要进行解引用操作(但不一定要将解引出来分配给字段符号后再能使用,可以直接使用解引用出来的内容,参看前面):
ASSIGN <dref>->* TO <FS> [CASTING ...].
.
dref2 = dref.
ASSIGN dref2->* to <fs2>.
WRITE: / <fs2>.
100
但如果数据引用是一个指向某个结构的数据对象时,可以直接通过结构对象引用(指针)来访问其成员,这与普通数据变量对象引用有所区别:
TYPES: BEGIN OF strc,
comp ,
END OF strc.
DATA ref TYPE REF TO strc.
CREATE DATA ref TYPE strc.
"可以直接使用结构引用(指针)访问其成员
ref->comp = 'X'.
"也可这样:先解引用结构对象,再访问其成员,这也是标准访问方式
"ref->*-comp = 'X'.
"通过指针直接进行访问成员
WRITE: / ref->comp.
FIELD-SYMBOLS: <dref> TYPE strc.
ASSIGN ref->* TO <dref>.
"通过结构体对象本身来访问成员
WRITE: / <dref>-comp.