Either use byte code analysis or time the two approaches using System.nanoTime
. I think second one is faster. here is what I did to conclude this:
I wrote three classes as given below:
public static class A {
public B b = new B();
}
public static class B {
public E e = new E();
}
public static class E {
public String name = "s";
public int age = 1;
}
Then I wrote two simple methods and get their java byte code using javap -c CLASS_NAME
.
public static void Test1() {
A a = new A();
String str = a.b.e.name;
int age = a.b.e.age;
}
The byte code of above method is:
public static void Test1();
Code:
// new A();
0: new #15
3: dup
4: invokespecial #17
7: astore_0
8: aload_0
// a.b (it accesses the field and put it on operand stack)
9: getfield #18
// b.e
12: getfield #22
// b.name
15: getfield #28
// pop 'name' from stack
18: astore_1
19: aload_0
// cyle continues
20: getfield #18
23: getfield #22
26: getfield #34
29: istore_2
30: return
You can clearly see at byte code level, each time you try to access field, it put the value of that filed on stack and then this cycle continues. Therefore, a.a1.a2....an
would be n
instruction if stack would have enough spae to hold all n
. And there was no optimisation by compiler this same cycle of called again to access both name
and age
field.
Now here is the second method:
public static void Test2() {
A a = new A();
E e = a.b.e;
String str = e.name;
int age = e.age;
}
Byte code for above method is:
public static void Test2();
Code:
// new A();
0: new #15
3: dup
4: invokespecial #17
7: astore_0
8: aload_0
// store a.b.e on operand stack once
9: getfield #18
12: getfield #22
15: astore_1
16: aload_1
// get 'name' field
17: getfield #28
20: astore_2
21: aload_1
// get 'age' field
22: getfield #34
25: istore_3
26: return
Above is 4 instruction shorter than previous code as it prevents execution of getfield
. So I think this should be faster than previous one.