Home > Mobile >  Calling method twice in same block. Why?
Calling method twice in same block. Why?

Time:10-21

I'm reading a blog post and trying to understand what's going on. This is the blogpost.

it has this code:

if (validation().hasErrors()) 
      throw new IllegalArgumentException(validation().errorMessage());

In the validation() method we have some object initialization and calculations so let' say it's an expensive call. Is it going to be executed twice? Or will it be optimized by the compiler to be something like this?

var validation = validation();
if (validation.hasErrors()) 
    throw new IllegalArgumentException(validation.errorMessage());

Thanks!

CodePudding user response:

The validation method will be called twice, and it will do the same work each time. First, the method is relatively big, and so it won't get inlined. Without being inlined, the compiler doesn't know what it does. Therefore, it safely assumes that the method has side effects, and so it cannot optimize away the second call.

Even if the method was inlined, and the compiler could examine it, it would see that there are in fact side effects. Calling LocalDate.now() returns a different result each time. For this reason, the code that you linked to is defective, although it's not likely to experience a problem in practice.

It's safer to capture the validation result in a local variable not for performance reasons, but for stability reasons. Imagine the odd case in which the initial validation call fails, but the second call passes. You'd then throw an exception with no message in it.

CodePudding user response:

The Java to Bytecode compiler has a limited set of optimization techniques (e.g. 9*9 in the condition would turn into 81).

The real optimization happens by the JIT (Just In Time) compiler. This compiler is the result of over a decade and a half of extensive research and there is no simple answer to tell what it is capable of in every scenario.

With that being said, as a good practice, I always handle repetitive identical method calls by storing their result before approaching any loop structure where that result is needed. Example:

int[] grades = new int[500];
short countOfGrades = (short) arr.length;
for (short i = 0; i < countOfGrades; i  ) {
    // Some code here
}

Notice that I'm using the short type to reduce the space complexity since the array size is less than 2^16 = 65,536 (short is 16-bits in Java).

For your code (which is only run twice), you shouldn't worry as much about such optimization. But if you're looking for the ultimate – guaranteed – optimization on the account of a fraction of space (which is cheap), then you're better off using a variable to store any identical method result when needed more than once:

var validation = validation();
if (validation.hasErrors()) 
    throw new IllegalArgumentException(validation.errorMessage());

CodePudding user response:

However, I must simply question ... "these days," does it even actually matter anymore? Simply write the source-code "in the most obvious manner available," as the original programmer certainly did.

"Microseconds" really don't matter anymore. But, "clarity still does." To me, the first version of the code is frankly more understandable than the second, and "that's what matters to me most." Please don't bother to try to "out-smart" the compiler, if it results in source-code that is in any way harder to understand.

  • Related