相比较于一般的数据类型(例如 I, P, F, N, C, D, T等)的变量,Field Symbol和Data Reference类型的变量是ABAP中两个相关复杂的类型。理解和使用这两种变量,对于编写高性能、高灵活性的ABAP程序是十分重要的。
1.含义解析
- Field Symbol:类似于C语言中的“指针”。初始状态为Unassigned。Field Symbol类型的变量自身并不对占用存储空间,仅“指向”被Assgined变量的地址空间。
- Data Reference: 一种变量类型。初始状态为Initial。当被创建(实例化)成具体的类型时,系统会为其分配相应的存储空间。通过 ‘ ->* ’ 的方式访问,将值从地址空间传输到变量中(显示)。若要改变Data Reference变量中的值,需要配合Field Symbol使用。即使用Field Symbol指向Data Reference变量所存储的地址空间,并用Field Symbol对其进行操作。
下图给出了配合Field Symbol操作Data Reference的一个例子 -
2. 使用Field Symbol提升访问效率
因为Field Symbol并不会占用内存空间,因此在操作变量时,可以使用Field Symbol来提升运行效率。常用的Field Symbol的场景有以下几种 -
- Read table < itab > assigning < fs >
- Loop at < itab > assigning < fs >
- Assign < data object > to < fs >
- Assign component <component name/component index> to < fs >
- Append initial line to < itab > assigning < fs >
**********************************************************************
* Field Symbol to prioritize the accessing of internal table
**********************************************************************
DATA: lt_sflight TYPE STANDARD TABLE OF sflight,
ls_sflight TYPE sflight.
FIELD-SYMBOLS: <ls_sflight> TYPE sflight.
SELECT * FROM sflight INTO TABLE lt_sflight UP TO 10 ROWS.
* extra effort to copy data into variable ls_sflight
LOOP AT lt_sflight INTO ls_sflight.
WRITE: / ls_sflight-carrid, ls_sflight-connid, ls_sflight-fldate.
ENDLOOP.
* access the address directly
LOOP AT lt_sflight ASSIGNING <ls_sflight>.
WRITE: / <ls_sflight>-carrid, <ls_sflight>-connid, <ls_sflight>-fldate.
ENDLOOP.
3.使用Data Reference动态创建变量
使用Data Reference的主要场景是针对于unknown的变量类型,用于ABAP的动态编程。创建所需要的变量时并不能确定具体的类型(但这里并不是指“漫无边际”的不确定,需要变量/结构/内表是确定的,而所需要的具体类型是不确定的) -
- 创建时,并无法确定具体类型的“变量 variable”
- 创建时,并无法确定具体类型的“结构 structure”
- 创建时,并无法确定具体类型的“内表 internal table”
下面给出了,三个不同场景的具体例子:
**********************************************************************
* 1. Un known data reference(creation of data variable)
**********************************************************************
PARAMETERS: p_var TYPE string DEFAULT 'I'.
DATA: lr_data TYPE REF TO data.
CREATE DATA lr_data TYPE (p_var).
FIELD-SYMBOLS: <fs> TYPE any.
ASSIGN lr_data->* TO <fs>.
IF sy-subrc = 0.
<fs> = '100'.
ENDIF.
WRITE: <fs>.
**********************************************************************
* 2. Un known data reference(creation of structure)
**********************************************************************
PARAMETERS: p_var TYPE string DEFAULT 'SFLIGHT'.
DATA: lr_data TYPE REF TO data.
CREATE DATA lr_data TYPE (p_var).
FIELD-SYMBOLS: <fs> TYPE any.
ASSIGN lr_data->* TO <fs>.
IF sy-subrc = 0.
SELECT SINGLE * FROM (p_var) INTO <fs>.
IF sy-subrc = 0.
FIELD-SYMBOLS: <fs_field> TYPE any.
DO .
ASSIGN COMPONENT sy-index OF STRUCTURE <fs> TO <fs_field>.
IF sy-subrc = 0.
WRITE: / <fs_field>.
ELSE.
EXIT.
ENDIF.
ENDDO.
ENDIF.
ENDIF.
**********************************************************************
* 3. Un known data reference(creation of table)
**********************************************************************
PARAMETERS: p_var TYPE string DEFAULT 'SFLIGHT'.
DATA: lr_data TYPE REF TO data.
CREATE DATA lr_data TYPE TABLE OF (p_var).
FIELD-SYMBOLS: <ft_table> TYPE ANY TABLE.
ASSIGN lr_data->* TO <ft_table>.
IF sy-subrc = 0.
SELECT * FROM (p_var) INTO TABLE <ft_table> UP TO 10 ROWS.
IF sy-subrc = 0.
cl_salv_table=>factory( IMPORTING r_salv_table = DATA(lr_salv)
CHANGING t_table = <ft_table> ).
lr_salv->display( ).
ENDIF.
ENDIF.