Jerry Brady
Jerry Brady

Reputation: 3079

Is declaring a local variable and setting it once more efficient than using a getter over and over?

I was going through some code today and saw this:

    x.add(getResources().getString(R.string.none));
    x.add(getResources().getString(R.string.today));
    x.add(getResources().getString(R.string.tomorrow));
    ...

and so I thought, "that's inefficient!" and started to change it to:

    Resources res = getResources();
    x.add(res.getString(R.string.none));
    x.add(res.getString(R.string.today));
    x.add(res.getString(R.string.tomorrow));
    ...

but then I stopped and wondered: Is the second section of code really more efficient or does it not really matter? Is the compiler going to generate the same byte code either way?

Upvotes: 0

Views: 272

Answers (6)

Steve J
Steve J

Reputation: 2674

The milliseconds difference between the two is nothing in comparison to the hours spent debugging this mistake:

x.add(getNewResources().getString(R.string.none));
x.add(getResources().getString(R.string.today));
x.add(getResources().getString(R.string.tomorrow));

Oops. The person updating the code was not sufficiently familiar with it and did not appreciate that all the getStrings had to come from the NewResource, not just the first one. He made the change, compiled it, delivered it, and now strange things are happening, and no one knows why.

In your second code fragment, you communicate to the reader of the code that there is a common place from which all the strings are extracted by actually creating a common place called "res".

Upvotes: 2

Pal Szasz
Pal Szasz

Reputation: 3225

Never trust the optimization of the compiler, I was disappointed in it several times. And in this case the java compiler cannot know if the getResources() method has any side effect or not (like locking an object, incrementing a counter), since when you build your project, it's compiled against the stub api, not the real code. The JIT is running inside the phone, so it's usually not as smart as a desktop compiler.

Also I think the preferred way would be:

final Resources res = getResources();
x.add(res.getString(R.string.none));
x.add(res.getString(R.string.today));
x.add(res.getString(R.string.tomorrow));
...

The final keyword usually helps the compiler in optimization.

Upvotes: 4

Malcolm
Malcolm

Reputation: 41498

Developer's Guide doesn't recommend using getters when you can use direct field access: Avoid Internal Getters/Setters.

Without a JIT, direct field access is about 3x faster than invoking a trivial getter. With the JIT (where direct field access is as cheap as accessing a local), direct field access is about 7x faster than invoking a trivial getter.

However, it won't make much of a difference unless you make many calls. So I would go with the most readable variant, which is in my opininon the second one since it has less clutter.

Upvotes: 1

Mark Rotteveel
Mark Rotteveel

Reputation: 109255

I would simply opt for the second version because it is a lot easier to read. You should not care about the potentially trivial performance impact, choosing readability over performance concerns is almost always the better choice.

Most likely in this trivial piece of code there will be no effect because the JIT will eventually generate the same code (although I am not sure if the Dalvik JVM is as good in jitting as the Java JVM is).

Upvotes: 1

Kashyap
Kashyap

Reputation: 17546

Yes. The Java compilers are MUCH smarter than they were 10 years back. This would certainly optimized if the implementation of getResource() is { return xxx; }. But compilers are capable of doing even better optimizations. E.g.

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1503599

The compiler will not generate the same byte code, but if getResources() is a trivial method then the JIT-compiler may effectively run the same code at execution time.

Personally I prefer the second form on the grounds of it being cleaner and more readable rather than for performance reasons.

Upvotes: 4

Related Questions