ABAP Data References: REF, GET REFERENCE and Dereferencing

Category
ABAP-Statements
Published
Author
Johannes

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 reference
DATA: lr_data TYPE REF TO <data_type>.
" Generic reference (to any data)
DATA: lr_any TYPE REF TO data.
" Inline declaration
DATA(lr_inline) = REF #( variable ).

Create Reference

" Modern (from 7.40): REF #()
lr_data = REF #( variable ).
" Classic: GET REFERENCE
GET REFERENCE OF variable INTO lr_data.
" Create new data object
CREATE DATA lr_data TYPE <type>.
lr_data = NEW #( ). " From 7.40

Dereferencing

" Access the data
<value> = lr_data->*.
" For structures: Component access
<value> = lr_struct->comp_name.
" For tables: Access to rows
LOOP 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 variable
lr_number = REF #( lv_number ).
" Dereferencing: Read value
WRITE: / 'Value:', lr_number->*. " 42
" Dereferencing: Change value
lr_number->* = 100.
WRITE: / 'Original:', lv_number. " 100 (changed!)

2. Check Reference

DATA: lr_data TYPE REF TO string.
" Check if reference is valid
IF 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 reference
FREE lr_data.

3. GET REFERENCE (Classic Syntax)

DATA: lv_text TYPE string VALUE 'Hello World'.
DATA: lr_text TYPE REF TO string.
" Classic syntax
GET REFERENCE OF lv_text INTO lr_text.
WRITE: / lr_text->*. " Hello World

4. Create New Data Object

DATA: lr_number TYPE REF TO i.
" Classic: CREATE DATA
CREATE DATA lr_number.
lr_number->* = 42.
" Modern: NEW #()
DATA(lr_string) = NEW string( 'New String' ).
WRITE: / lr_string->*.
" With type
DATA: lr_any TYPE REF TO data.
CREATE DATA lr_any TYPE i.
" Generic with dynamic type
DATA: 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 LOOP
LOOP 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 INTO
READ 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 references
APPEND REF #( lv_str1 ) TO lt_refs.
APPEND REF #( lv_str2 ) TO lt_refs.
APPEND REF #( lv_str3 ) TO lt_refs.
" Iterate through references
LOOP AT lt_refs INTO DATA(lr_str).
WRITE: / lr_str->*.
ENDLOOP.
" Change original values via references
READ TABLE lt_refs INTO lr_str INDEX 1.
lr_str->* = 'CHANGED'.
WRITE: / lv_str1. " CHANGED

7. 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.
" Usage
DATA: 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. " 100

8. Generic References (REF TO data)

DATA: lr_any TYPE REF TO data.
FIELD-SYMBOLS: <fs_data> TYPE any.
" Reference to Integer
DATA(lv_int) = 42.
lr_any = REF #( lv_int ).
" For access: Assign field symbol
ASSIGN lr_any->* TO <fs_data>.
WRITE: / <fs_data>.
" Reference to String
DATA(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 object
CREATE DATA lr_data TYPE (lv_type).
" Assign value via field symbol
FIELD-SYMBOLS: <fs> TYPE any.
ASSIGN lr_data->* TO <fs>.
<fs> = 'Dynamically created'.
WRITE: / <fs>.
" For structures
DATA: 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'. " Yes
ENDIF.
IF lr_ref1 = lr_ref2.
WRITE: / 'ref1 and ref2 are identical'. " No! (different references)
ENDIF.
" Value comparison
IF lr_ref1->* = lr_ref2->*.
WRITE: / 'Values are equal'. " Yes
ENDIF.

Data Reference vs. Field Symbol

AspectData ReferenceField Symbol
TypeVariable (REF TO)Placeholder
StoreYes, can be storedNo, only temporary
PassCan be passed as parameterOnly locally usable
NULL stateCan be initial/unboundNot assigned
Syntaxlr_data->*<fs>
PerformanceMinimally slowerMinimally faster
Use caseStore, pass aroundFast local access
" Field symbol: Faster local access
LOOP AT lt_data ASSIGNING FIELD-SYMBOL(<fs>).
<fs>-field = 'X'.
ENDLOOP.
" Data reference: When reference must be stored
LOOP AT lt_data REFERENCE INTO DATA(lr_line).
APPEND lr_line TO lt_references. " Store reference
ENDLOOP.

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 references
TYPES: 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 BOUND before dereferencing.
  • Use REF #() instead of GET REFERENCE in modern ABAP.
  • Field symbols are more performant for local access.
  • Data references are needed when references must be stored or passed.
  • CREATE DATA for dynamic type determination at runtime.
  • Be careful with generic references (REF TO data) – type safety is lost.
  • Combine with LOOP AT ... REFERENCE INTO for efficient table access.
  • Use references in CLASS attributes for object relationships.