When I first begin to program with ABAP I get confused with different kinds of integer type available for ABAP developers: i, int1, int2, int4, and int8.
According to ABAP help, predefined data types consists of two types:
(1) predefined ABAP types: b, c, d, decfloat16, decfloat34, f, i, int8, n, p, s, string, t, x, and xstring.
(2) predefined dictionary types: INT1, INT2, INT4, INT8,DEC,DF16_DEC,DF16_RAW,DF34_DEC,DF34_RAW and FLTP.
How to understand the difference between these two types
The predefined dictionary types could be used to define other dictionary datatype:
However it is not possible to use a predefined ABAP type:
All these five types could be directly used in ABAP code to define the type of a variable, and i and int4 have the same technical type, see example below:
Value range of each type
The range of each types could be calculated via formula:
where n = 2, 4, 8.
For n = 1, since int1 is unsigned char, all the whole 8 bit of 1 byte could be used to represent the numeric value, so the range should then be:
The constant range of int4 and int8 are defined in class CL_ABAP_MATH:
while int1 and int2 are defined in another class CL_ABAP_EXCEPTIONAL_VALUES:
Integer and RTTI
Test via the following code:
DATA: lv1 TYPE i VALUE 1,
lv2 TYPE int1 VALUE 1,
lv3 TYPE int2 VALUE 1,
lv4 TYPE int4 VALUE 1,
lv5 TYPE int8 VALUE 1.
DATA: lv1_copy TYPE i VALUE 2,
lv2_copy TYPE int1 VALUE 2.
DATA(lo1) = cl_abap_typedescr=>describe_by_data( lv1 ).
DATA(lo2) = cl_abap_typedescr=>describe_by_data( lv2 ).
DATA(lo3) = cl_abap_typedescr=>describe_by_data( lv3 ).
DATA(lo4) = cl_abap_typedescr=>describe_by_data( lv4 ).
DATA(lo5) = cl_abap_typedescr=>describe_by_data( lv5 ).
DATA(lo1_copy) = cl_abap_typedescr=>describe_by_data( lv1_copy ).
DATA(lo2_copy) = cl_abap_typedescr=>describe_by_data( lv2_copy ).
Result shows that lo1 and lo1_copy point to the same element descriptor reference since they are both performed on variable with the same type i.
The same holds true for lo2 and lo2_type ( int1 ).
Although i and int4 have the same technical type, however since their absolute type are different, so different descriptor reference are returned ( lo1 and lo4 ).
Value comparison and reference comparison
It is not difficult to forecast the result of test below:
DATA: lv_i1 TYPE i VALUE 1,
lv_i2 TYPE int4 VALUE 1,
lv_i3 TYPE int8 VALUE 1,
lv_i4 TYPE int4 VALUE 1.
WRITE: / 'l1 = l2?' , boolc( lv_i1 EQ lv_i2 ).
WRITE: / 'l1 = l3?' , boolc( lv_i1 EQ lv_i3 ).
WRITE: / 'l2 = l3?' , boolc( lv_i2 EQ lv_i3 ).
DATA: lo_i1 TYPE REF TO i,
lo_i2 TYPE REF TO int1,
lo_i3 TYPE REF TO int2.
lo_i1 = NEW #( 1 ).
lo_i2 = NEW #( 1 ).
lo_i3 = NEW #( 1 ).
WRITE: / 'o1 = o2?' , boolc( lo_i1 EQ lo_i2 ).
WRITE: / 'o1 = o3?' , boolc( lo_i1 EQ lo_i3 ).
WRITE: / 'o2 = o3?' , boolc( lo_i2 EQ lo_i3 ).
WRITE: / 'o1->* = o2->* ?' , boolc( lo_i1->* EQ lo_i2->* ).
WRITE: / 'o1->* = o3->* ?' , boolc( lo_i1->* EQ lo_i3->* ).
WRITE: / 'o2->* = o3->* ?' , boolc( lo_i2->* EQ lo_i3->* ).
Integer in Java
Before we start the explore in Java, see the following crazy code:
Yes, 2 + 2 = 5 in Java?!
Before I unveil the source code of method doSomethingMagic,
let’s first see another example which is easier to understand.
I perform the accumulation from 0 to 10000 and repeat it for 10000 times. I did this operation twice with different approaches: calc1 and calc2. The logic inside the two methods are exactly the same except that different types are used for iterator variable i and variable to store add result in each loop.
public class IntegerCompare {
private static long start;
private static void start(){
start = System.currentTimeMillis();
}
private static long end(){
return System.currentTimeMillis() - start;
}
private static final int NUM = 10000;
private static int calc1(){
Integer result = 0;
for( Integer i = 0; i < NUM; i++){
result += i;
}
return result;
}
private static int calc2(){
int result = 0;
for( int i = 0; i < NUM; i++){
result += i;
}
return result;
}
public static void main(String[] args) {
System.out.println("Calc1: " + calc1());
System.out.println("Calc2: " + calc2());
start();
for( int i = 0; i < NUM; i++){
calc1();
}
System.out.println("Calc1 time: " + end());
start();
for( int i = 0; i < NUM; i++){
calc2();
}
System.out.println("Calc2 time: " + end());
}
}
The printed time shows that the second approach has much better performance than the first.
Decompile the .class file and we can know the reason of this performance difference. In the first solution, there are lots of object instance method call intValue and static method call Integer.valueOf which are much expensive compared with operations against primitive type int.
There is so called Autoboxing and unboxing in Java Specification. Autoboxing is the automatic conversion that the Java compiler makes between the primitive types and their corresponding object wrapper classes. For example when you write the following code:
Integer a = 10;
Decompile the .class file and we find that Java compiler translate the code into:
Integer a = Integer.valueOf(10);
It is the very huge amount of Autoboxing operations in the first approach which leads to a poor performance compared with the second solution.
Why 2 + 2 = 5?
Now it’s time to go back to the mysterious method doSomethingMagic in the example.
First check how Integer.valueOf is implemented in JDK. Nothing special there, ABAPer should be very familiar with such style: first check whether the primitive value to be boxed has already corresponding buffered instance in IntegerCache.cache ( just consider it as an internal table in ABAP ). If buffer hits, directly return the entry, otherwise instantiate a new boxed instance. By default the buffer logic only cover the range -128 ~ 127.
Now let’s see the source code of doSomethingMagic, where one entry in Integer buffer maintained by IntegerCache.cache is modified by reflection.
The 132nd entry, which originally represents for primitive value 4, is now overwritten by 133rd entry ( primitive value 5 ).
And 2 + 2 is actually converted by Compiler as Integer.valueOf(4) in compilation time:
So finally “5” is returned as the result of Integer.valueOf(4):
Last but not the least, in ABAP we have similar utility method as Integer.valueOf in Java which converts the input Char like value into a real INT8 value.
Integer in JavaScript
Since now we already the knowledge of Autoboxing and unboxing, it is pretty easy to understand the logic in JavaScript as well.
In Java it is not possible to perform any method call on an variable with primitive type:
However it is possible in JavaScript. Check the examples below, where the autoboxing occurs – an new Number object is created under the hood.
(1).toString() equals to code below:
var a = new Number(1);
a.toString();
Further reading
I have written a series of blogs which compare the language feature among ABAP, JavaScript and Java. You can find a list of them below:
- Lazy Loading, Singleton and Bridge design pattern in JavaScript and in ABAP
- Functional programming – Simulate Curry in ABAP
- Functional Programming – Try Reduce in JavaScript and in ABAP
- Simulate Mockito in ABAP
- A simulation of Java Spring dependency injection annotation @Inject in ABAP
- Singleton bypass – ABAP and Java
- Weak reference in ABAP and Java
- Fibonacci Sequence in ES5, ES6 and ABAP
- Java byte code and ABAP Load
- How to write a correct program rejected by compiler: Exception handling in Java and in ABAP
- An small example to learn Garbage collection in Java and in ABAP
- String Template in ABAP, ES6, Angular and React
- Try to access static private attribute via ABAP RTTI and Java Reflection
- Local class in ABAP, Java and JavaScript
- Integer in ABAP, Java and JavaScript
- Covariance in Java and simulation in ABAP
- Various Proxy Design Pattern implementation variants in Java and ABAP
- Tag(Marker) Interface in ABAP and Java
- Bitwise operation ( OR, AND, XOR ) on ABAP Integer
- ABAP ICF handler and Java Servlet
要获取更多Jerry的原创文章,请关注公众号"汪子熙":