Premature optimization in Java: when to use “x = foo.getX()” vs simply “foo.getX()”

送分小仙女□ 提交于 2019-12-04 01:53:13

The choice shouldn't really be about performance hit but about code readability.

When you create a variable you can give it the name it deserves in the current context. When you use a same value more than one time it has surely a real meaning, more than a method name (or worse a chain of methods).
And it's really better to read:

String username = user.getName();
SomeMethod1(a, b, username, c);
SomeMethod2(b, username, c);
SomeMethod3(username);

than

SomeMethod1(a, b, user.getName(), c);
SomeMethod2(b, user.getName(), c);
SomeMethod3(user.getName());

For plain getters - those that just returns a value - HotSpot inlines it in the calling code, so it will be as fast as it can be.

I, however, have a principle about keeping a statement on a single line, which very often results in expressions like "foo.getBar()" being too long to fit. Then it is more readable - to me - to extract it to a local variable ("Bar bar = foo.getBar()").

They could be 2 different things.

If GetX is non-deterministic then the 1st one will give different results than the 2nd

Personally, I'd use the 2nd one. It's more obvious and less unnecessarily verbose.

I use the second style if it makes my code more readable or if I have to use the assigned value again. I never consider performance (on trivial things) unless I have to.

That depends on what getX() actually does. Consider this class:

public class Foo {
    private X x;

    public X getX() { return x; }
}

In this case, when you make a call to foo.getX(), JVM will optimize it all the way down to foo.x (as in direct reference to foo's private field, basically a memory pointer). However, if the class looks like this:

public class Foo {
    private X x;

    public X getX() { return cleanUpValue(x); }

    private X cleanUpValue(X x) {
        /* some modifications/sanitization to x such as null safety checks */
    }
}

the JVM can't actually inline it as efficiently anymore since by Foo's constructional contract, it has to sanitize x before handing it out.

To summarize, if getX() doesn't really do anything beyond returning a field, then there's no difference after initial optimization runs to the bytecode in whether you call the method just once or multiple times.

Most of the time I would use getX if it was only once, and create a var for it for all other cases. Often just to save typing.

With regards to performance, the compiler would probably be able to optimize away most of the overhead, but the possibility of side-effects could force the compiler into more work when doing multiple method-calls.

I generally store it locally if:

  1. I'm will use it in a loop and I don't want or expect the value to change during the loop.

  2. I'm about to use it in a long line of code or the function & parameters are very long.

  3. I want to rename the variable to better correspond to the task at hand.

  4. Testing indicates a significant performance boost.

Otherwise I like the ability to get current values and lower level of abstraction of method calls.

Two things have to be considered:

  1. Does the call to getX() have any side effects? Following established coding patterns, a getter should not alter the object on which it is called, the in most cases, there is no side effect. Therefore, it is semantically equivalent to call the getter once and store the value locally vs. calling the getter multiple times. (This concept is called idempotency - it does not matter whether you call a method once or multiple times; the effect on the data is exactly the same.)

  2. If the getter has no side effect, the compiler can safely remove subsequent calls to the getter and create the temporary local storage on its own - thus, the code remains ultra-readable and you have all the speed advantage from calling the getter only once. This is all the more important if the getter does not simply return a value but has to fetch/compute the value or runs some validations.

Assuming your getter does not change the object on which it operates it is probably more readable to have multiple calls to getX() - and thanks to the compiler you do not have to trade performance for readability and maintainability.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!