Search code examples
javaandroidvirtualfinal

Are public getters and setters fine for Android if made final? Is final-correctness as important in Java as const-correctness is in C++?


I was reading this: http://developer.android.com/training/articles/perf-tips.html

Particularly this about internal getters and setters:

Virtual method calls are expensive, much more so than instance field lookups. It's reasonable to follow common object-oriented programming practices and have getters and setters in the public interface, but within a class you should always access fields directly.

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.

It mentions "virtual method calls" which, probably, also refer to public methods. I have a bunch of methods in my class where the methods shouldn't be overridden. For example:

public class Something {
    private float m_Float = 0.0f;
    public float getFloat () {
        return m_Float;
    }
}

I always want 'getFloat()' to return 'm_Float', even in derived classes. Does marking the method 'final' improve performance for Android devices? Even if it doesn't, is final-correctness as important as const-correctness? Like, do Java programmers get anal when fellow colleagues forget about final-correctness?

If marking the method final improves performance, is the performance gain nullified for the following?

public class Base {
    public int getRandomNumber () {
        return 4; //chosen by fair dice roll.
                  //guaranteed to be random.
    }
}
public class Derived extends Base {
    public final int getRandomNumber () {
        return 6; //chosen by second fair dice roll.
                  //guaranteed to be more random.
    }
}

I'm not really interested in optimizing my code at this point but I am interested in the final-correctness bit.. I'm not familiar with the standard conventions where Java's concerned.

[EDIT]

Okay, so, above, this link is given as a possible answer: Android Performance - 'Avoid Internal Getters/Setters'

The reply marked as the answer links to this: What optimizations can I expect from Dalvik and the Android toolchain?

It seems that simple getters and setters are inlined now.

In Gingerbread we added simple inlining for getters/setters. Since the underlying JIT frontend is still simple trace based, if the callee has branches in there it won't be inlined. But the inline cache mechanism is implemented so that virtual getters/setters can be inlined without problems.

And in the comments, this is asked:

(3) Should I declare my methods final wherever possible? Or does that still count as a virtual callsite?

And this is the reply:

(3) Yes please

So, with the comments here and whatnot, I'd say everything's resolved. (Except for when final should be used with methods; but that will probably be answered very soon. I have a belief but am waiting for it to get validated or refuted with a reason, so..)

[EDIT]

Also, doesn't this mean that the Android docs. about performance tips is.. outdated?


Solution

  • Personally, I would recommend not using final for anything other than constants. In quite a few years of development I really haven't seen a good use for final other that static final ... for constants. The final keyword is particularly vexing when it comes to testing - java.net.URL being a final class requires using things like PowerMock if you really want high test coverage.

    When in doubt, develop realistic performance tests and profile the two scenarios. If there is no discernible difference, then don't add restrictions like final to your code. Statements like:

    direct field access is about 3x faster than invoking a trivial getter

    is quite meaningless without some real numbers. If invoking a trivial getter only takes a 20 microseconds, then increasing the cost to 60 microseconds is meaningless. For mobile applications, getters & setters aren't going to cause your performance problems.

    Always code for correctness first, readability second, and maintainability after that.