开发者

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

When I find myself calling the same getter method multiple times, should t开发者_Go百科his be considered a problem? Is it better to [always] assign to a local variable and call only once?

I'm sure the answer of course is "it depends".

I'm more concerned about the simpler case where the getter is simply a "pass-along-the-value-of-a-private-variable" type method. i.e. there's no expensive computation involved, no database connections being consumed, etc.

My question of "is it better" pertains to both code readability (style) and also performance. i.e. is it that much of a performance hit to have:

SomeMethod1(a, b, foo.getX(), c);
SomeMethod2(b, foo.getX(), c);
SomeMethod3(foo.getX());

vs:

X x = foo.getX();
SomeMethod1(a, b, x, c);
SomeMethod2(b, x, c);
SomeMethod3(x);

I realize this question is a bit nit-picky and gray. But I just realized, I have no consistent way of evaluating these trade-offs, at all. Am fishing for some criteria that are more than just completely whimsical.

Thanks.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜