Vishal Jumani Vishal Jumani - 22 days ago 6
Java Question

Java - Nested Level object assignment

I am currently working with a lot of nested level objects and was thinking about performance.

So let's say I have the following classes:

class Address {
private String doorNumber;
private String street;
...
}


and another class Customer.

class Customer {
private List<Address> addressList;
private String firstName;
.....
.....
.....
}


and when I try to access it like below:

public static void main(String[] str) {
Customer customer = new Customer();
// ... and add addresses to this Customer object.

// Set 1
// And if I then do...
customer.getAddressList().get(0).getHouseNumber();
customer.getAddressList().get(0).getStreet();

// OR
// Set 2
Address address = customer.getAddressList().get(0);
address.getHouseNumber();
address.getStreet()
}


I know the first set of lines to access the Address is not clean code, and I assumed the compiler would sort this out but it doesn't. Because when I decompile my code, I get exactly the same thing back so am not sure if the compiler is doing any optimisations there. So my first question is why doesn't the compiler clean this up and assign it to a temporary variable?

And my next question is, is this something to do with performance? And which is the more optimal performant code of the two, apart from the first not being very clean code. Does it mean, that my 2nd set of lines of code would internally get translated to the first during compilation?

And finally the last one, is it more optimal to call variables on a class than its getter method? Am just thinking performance here without clean coding.

Answer

Side effects.

Consider this case, where instead of returning some text, calling your get method has some internal side effect:

// This goes up each time getAddressList is called.
public int addressesRequested;

public List<Address> getAddressList(){
    addressesRequested++;
    return addressList;
}

Of course, in this method such a side effect doesn't make much sense, but there are a wide variety of ways in which a method call can leave some form of left over effect.

customer.getAddressList(); // addressesRequested is now 1.
customer.getAddressList(); // addressesRequested is now 2.
...

As a result, the compiler can't optimise multiple method calls into one - it has to assume that a method call has side effects.

It's also worth noting that a method can also be inlined - that's where the body of the method is copied to the call site to avoid a method calls overhead. This generally only happens when the JVM believes such an optimization is merited; i.e. because it's being called frequently. It does not, however, result in the callsite being optimised any further - it won't trigger some kind of temporary variable there.