Data references in ABAP are typed pointers that point to data objects in memory. Unlike field symbols, which point directly to memory, data references are independent variables that store an address.
Basic Concept
- A data reference is a variable that contains the memory address of a data object
- It can be passed around, stored and compared
- Access to the data is done via dereferencing (
->*) - Data references can be initial (NULL)
Syntax
Declare Data Reference
" Typed referenceDATA: lr_data TYPE REF TO <data_type>.
" Generic reference (to any data)DATA: lr_any TYPE REF TO data.
" Inline declarationDATA(lr_inline) = REF #( variable ).Create Reference
" Modern (from 7.40): REF #()lr_data = REF #( variable ).
" Classic: GET REFERENCEGET REFERENCE OF variable INTO lr_data.
" Create new data objectCREATE DATA lr_data TYPE <type>.lr_data = NEW #( ). " From 7.40Dereferencing
" Access the data<value> = lr_data->*.
" For structures: Component access<value> = lr_struct->comp_name.
" For tables: Access to rowsLOOP AT lr_table->* INTO DATA(ls_line). ...ENDLOOP.System Fields
After operations with data references:
- Reference
IS BOUND: Points to valid data - Reference
IS INITIAL: Points to nothing (NULL)
Examples
1. Basic Usage
DATA: lv_number TYPE i VALUE 42.DATA: lr_number TYPE REF TO i.
" Create reference to variablelr_number = REF #( lv_number ).
" Dereferencing: Read valueWRITE: / 'Value:', lr_number->*. " 42
" Dereferencing: Change valuelr_number->* = 100.WRITE: / 'Original:', lv_number. " 100 (changed!)2. Check Reference
DATA: lr_data TYPE REF TO string.
" Check if reference is validIF lr_data IS BOUND. WRITE: / 'Reference points to:', lr_data->*.ELSE. WRITE: / 'Reference is NULL'.ENDIF.
IF lr_data IS INITIAL. WRITE: / 'Reference not initialized'.ENDIF.
" Release referenceFREE lr_data.3. GET REFERENCE (Classic Syntax)
DATA: lv_text TYPE string VALUE 'Hello World'.DATA: lr_text TYPE REF TO string.
" Classic syntaxGET REFERENCE OF lv_text INTO lr_text.
WRITE: / lr_text->*. " Hello World4. Create New Data Object
DATA: lr_number TYPE REF TO i.
" Classic: CREATE DATACREATE DATA lr_number.lr_number->* = 42.
" Modern: NEW #()DATA(lr_string) = NEW string( 'New String' ).WRITE: / lr_string->*.
" With typeDATA: lr_any TYPE REF TO data.CREATE DATA lr_any TYPE i.
" Generic with dynamic typeDATA: lv_typename TYPE string VALUE 'STRING'.CREATE DATA lr_any TYPE (lv_typename).5. References with Internal Tables
TYPES: BEGIN OF ty_customer, id TYPE i, name TYPE string, END OF ty_customer.
DATA: lt_customers TYPE TABLE OF ty_customer, lr_table TYPE REF TO ty_customer.
lt_customers = VALUE #( ( id = 1 name = 'Miller' ) ( id = 2 name = 'Smith' )).
" REFERENCE INTO in LOOPLOOP AT lt_customers REFERENCE INTO lr_table. WRITE: / lr_table->id, lr_table->name.
" Change via reference lr_table->name = to_upper( lr_table->name ).ENDLOOP.
" READ TABLE with REFERENCE INTOREAD TABLE lt_customers REFERENCE INTO lr_table WITH KEY id = 1.
IF sy-subrc = 0. lr_table->name = 'Changed'.ENDIF.6. Store References in Tables
DATA: lt_refs TYPE TABLE OF REF TO string.DATA: lv_str1 TYPE string VALUE 'One', lv_str2 TYPE string VALUE 'Two', lv_str3 TYPE string VALUE 'Three'.
" Collect referencesAPPEND REF #( lv_str1 ) TO lt_refs.APPEND REF #( lv_str2 ) TO lt_refs.APPEND REF #( lv_str3 ) TO lt_refs.
" Iterate through referencesLOOP AT lt_refs INTO DATA(lr_str). WRITE: / lr_str->*.ENDLOOP.
" Change original values via referencesREAD TABLE lt_refs INTO lr_str INDEX 1.lr_str->* = 'CHANGED'.WRITE: / lv_str1. " CHANGED7. Pass References to Methods
CLASS lcl_processor DEFINITION. PUBLIC SECTION. METHODS: process_data IMPORTING ir_data TYPE REF TO i.ENDCLASS.
CLASS lcl_processor IMPLEMENTATION. METHOD process_data. IF ir_data IS BOUND. ir_data->* = ir_data->* * 2. ENDIF. ENDMETHOD.ENDCLASS.
" UsageDATA: lv_value TYPE i VALUE 50, lo_proc TYPE REF TO lcl_processor.
lo_proc = NEW #( ).lo_proc->process_data( REF #( lv_value ) ).
WRITE: / lv_value. " 1008. Generic References (REF TO data)
DATA: lr_any TYPE REF TO data.FIELD-SYMBOLS: <fs_data> TYPE any.
" Reference to IntegerDATA(lv_int) = 42.lr_any = REF #( lv_int ).
" For access: Assign field symbolASSIGN lr_any->* TO <fs_data>.WRITE: / <fs_data>.
" Reference to StringDATA(lv_str) = |Hello|.lr_any = REF #( lv_str ).
ASSIGN lr_any->* TO <fs_data>.WRITE: / <fs_data>.9. Dynamic Object Creation
DATA: lr_data TYPE REF TO data, lv_type TYPE string VALUE 'STRING'.
" Dynamically create data objectCREATE DATA lr_data TYPE (lv_type).
" Assign value via field symbolFIELD-SYMBOLS: <fs> TYPE any.ASSIGN lr_data->* TO <fs>.<fs> = 'Dynamically created'.
WRITE: / <fs>.
" For structuresDATA: lv_struct_name TYPE string VALUE 'SFLIGHT'.CREATE DATA lr_data TYPE (lv_struct_name).ASSIGN lr_data->* TO <fs>.10. Reference Comparison
DATA: lv_data TYPE string VALUE 'Test'.DATA: lr_ref1 TYPE REF TO string, lr_ref2 TYPE REF TO string, lr_ref3 TYPE REF TO string.
lr_ref1 = REF #( lv_data ).lr_ref2 = REF #( lv_data ).lr_ref3 = lr_ref1.
" Reference comparison (point to same address?)IF lr_ref1 = lr_ref3. WRITE: / 'ref1 and ref3 are identical'. " YesENDIF.
IF lr_ref1 = lr_ref2. WRITE: / 'ref1 and ref2 are identical'. " No! (different references)ENDIF.
" Value comparisonIF lr_ref1->* = lr_ref2->*. WRITE: / 'Values are equal'. " YesENDIF.Data Reference vs. Field Symbol
| Aspect | Data Reference | Field Symbol |
|---|---|---|
| Type | Variable (REF TO) | Placeholder |
| Store | Yes, can be stored | No, only temporary |
| Pass | Can be passed as parameter | Only locally usable |
| NULL state | Can be initial/unbound | Not assigned |
| Syntax | lr_data->* | <fs> |
| Performance | Minimally slower | Minimally faster |
| Use case | Store, pass around | Fast local access |
" Field symbol: Faster local accessLOOP AT lt_data ASSIGNING FIELD-SYMBOL(<fs>). <fs>-field = 'X'.ENDLOOP.
" Data reference: When reference must be storedLOOP AT lt_data REFERENCE INTO DATA(lr_line). APPEND lr_line TO lt_references. " Store referenceENDLOOP.Typical Use Cases
1. Optional Parameters
METHODS: process IMPORTING ir_config TYPE REF TO ty_config OPTIONAL.
METHOD process. IF ir_config IS BOUND. " Use configuration ELSE. " Default values ENDIF.ENDMETHOD.2. Return References
METHODS: get_instance RETURNING VALUE(rr_instance) TYPE REF TO lcl_singleton.
METHOD get_instance. IF gr_instance IS NOT BOUND. gr_instance = NEW #( ). ENDIF. rr_instance = gr_instance.ENDMETHOD.3. Dynamic Data Structures
" Tree structure with referencesTYPES: BEGIN OF ty_node, value TYPE string, children TYPE TABLE OF REF TO ty_node WITH EMPTY KEY, END OF ty_node.
DATA: lr_root TYPE REF TO ty_node.lr_root = NEW #( value = 'Root' ).APPEND NEW ty_node( value = 'Child 1' ) TO lr_root->children.Important Notes / Best Practice
- Always check
IS BOUNDbefore dereferencing. - Use
REF #()instead ofGET REFERENCEin modern ABAP. - Field symbols are more performant for local access.
- Data references are needed when references must be stored or passed.
CREATE DATAfor dynamic type determination at runtime.- Be careful with generic references (
REF TO data) – type safety is lost. - Combine with
LOOP AT ... REFERENCE INTOfor efficient table access. - Use references in
CLASSattributes for object relationships.