Wednesday, 5 April 2017

Try to access static private attribute via ABAP RTTI and Java Reflection

In ABAP we can define a static attribute for a class via keyword CLASS-DATA, whose validity is not associated with instances of a class but with the class itself. In order to prove this fact I use the following simple Pointer class for demonstration:

class ZCL_POINT definition
  public
  final
  create public .
public section.

  data X type I .
  methods CONSTRUCTOR
    importing
      !IV_X type I
      !IV_Y type I .
private section.
  data Y type I .
  class-data COUNT type I .
ENDCLASS.
CLASS ZCL_POINT IMPLEMENTATION.
  method CONSTRUCTOR.
    me->x = iv_x.
    me->y = iv_y.
    count = count + 1.
  endmethod.
ENDCLASS.

In this class, static attribute count is responsible to maintain the number of created Point instances.
Then create four point instances:

data(a) = new zcl_point( iv_x = 1 iv_y = 1 ).
data(b) = new zcl_point( iv_x = 1 iv_y = 2 ).
data(c) = new zcl_point( iv_x = 1 iv_y = 3 ).
data(d) = new zcl_point( iv_x = 1 iv_y = 4 ).

Via any variable of a, b, c or d, we can monitor the value of count in debugger.

SAP ABAP Tutorials and Material, SAP ABAP Guide, SAP ABAP Certifications

Can we access the static attribute of a class without object instance in debugger?


Since in theory the static attribute belongs to class instead of any dedicated object instance, so question comes: is there approach to monitor the static attribute value in ABAP debugger directly from class instead? Yes it is possible.

1. type text “{C:ZCL_POINT} in debugger and press enter key

SAP ABAP Tutorials and Material, SAP ABAP Guide, SAP ABAP Certifications

2. double click, and you can see the attribute value is directly maintained in class ZCL_POINT, without any object instance created on top of it.

SAP ABAP Tutorials and Material, SAP ABAP Guide, SAP ABAP Certifications

And I try to change its visibility dynamically via class descriptor via the following code and actually it is not possible:

data(lo) = CAST cl_abap_objectdescr( cl_abap_classdescr=>describe_by_name( 'ZCL_POINT' ) ).

read TABLE lo->attributes ASSIGNING FIELD-SYMBOL(<count>) WITH KEY name = 'COUNT'.
CHECK SY-SUBRC = 0.
<count>-visibility = 'U'.

Since the structure is read-only and not editable outside cl_abap_objectdescr.

SAP ABAP Tutorials and Material, SAP ABAP Guide, SAP ABAP Certifications

This makes sense otherwise the encapsulation will be violated. Just check many other attribute marked as read-only in Class/Object descriptor class.

SAP ABAP Tutorials and Material, SAP ABAP Guide, SAP ABAP Certifications

Reflection in Java


Check the following code which demonstrates how to access private static attribute value in code via Reflection.
import java.lang.reflect.Field;

public class Point {
private int x;
private int y;
static private int count = 0;
public Point(int x, int y){
this.x = x;
this.y = y;
count++;
}
private static void accessStaticPrivate(Point point){
Class classObject = point.getClass();
try {
Field countField = classObject.getDeclaredField("count");
System.out.println("count: " + countField.get(point));
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException
| IllegalAccessException e1 ) {
e1.printStackTrace();
}
public static void main(String[] arg){
Point a = new Point(1,2);
accessStaticPrivate(a);
Point b = new Point(1,3);
accessStaticPrivate(b);
Point c = new Point(1,4);
accessStaticPrivate(c);
Point d = new Point(1,5);
accessStaticPrivate(d);
}
}

For ABAPer it is easy to understand the usage of Class object in Java by just comparing it with CL_ABAP_CLASSDESCR in ABAP.
When running this small program locally, you will get output in console:

count: 1
count: 2
count: 3
count: 4

No comments:

Post a Comment