Private static final vs private final in Java



  • Hi all,
    I have a question regarding Java runtime optimizations. I'm working on a project where constants relevant to a single class are declared:

    private static final

    These variables are never referenced in static methods, so the only reason for declaring them static would, I assume, be to ensure that only one instance of the variable is ever in the JVM - i.e., it's static for optimization purposes.

    My question is, in this case, does it really make sense to make these variables static? Or will the JVM realize at runtime that there's no reason to create more than one copy of these variables and make only one copy anyway? Is there a difference between how constants of primitive types and object constants are treated?

    I'm referring to Sun's JRE implementation, but if you have insights about other JVM's, I'd like to hear about it too.

    Thank you.

    Regards,
    Jack



  • I know little of Java in particular, but this doesn't sound like
    something you should be approaching from an optimizer's POV, unless
    there are lots of these constants or this class is in a critical
    section.  Instead, I would suggest approaching this from the POV
    of a class designer.



    If a piece of data or a method is owned by the class itself and not by
    any particular class instance, it should be made static.  It's
    usually easy to determine ownership: For variables, ask if the value
    changes from instance to instance.  If so, it should be owned by
    the instance.  For methods, ask if the method accesses instance
    methods or variables.  If so, they too should be owned by the
    instance.  Otherwise make them static.  Note this is just a
    rule of thumb.



    Constants are usually owned by the class.  Thus constants should usually be made static.



  • I agree with you that this shouldn't be approached from the optimizer's POV.

    I guess the reason I posted was because I've always felt that constants internal to an object instance (i.e., those that are referenced only be instance methods) should belong to an object instance, rather than the class.

    This is of course, a personal opinion, and perhaps I should rethink that...

    Regards,
    Jack

    @Chris F said:

    I know little of Java in particular, but this doesn't sound like something you should be approaching from an optimizer's POV, unless there are lots of these constants or this class is in a critical section.  Instead, I would suggest approaching this from the POV of a class designer.

    If a piece of data or a method is owned by the class itself and not by any particular class instance, it should be made static.  It's usually easy to determine ownership: For variables, ask if the value changes from instance to instance.  If so, it should be owned by the instance.  For methods, ask if the method accesses instance methods or variables.  If so, they too should be owned by the instance.  Otherwise make them static.  Note this is just a rule of thumb.

    Constants are usually owned by the class.  Thus constants should usually be made static.



  • There are no constants in Java, only literals and one-time-assignable-variables (those modified with the final keyword).



    References to static final variables are evaluated at compile time (if possible). Example:



    class A {

    static final int MAX = 12;

    }



    class B {

    A[] aa = new A[A.MAX];

    }



    Here the last assignment will actually produce bytecode equivalent to this:

    A[] aa = new A[12];



    So although there are no constants (and no headers files as in C/C++)
    in Java, you will have to recompile B if you change the value for A.MAX.



    Also note this:



    class C {

    static int nextId = 0;

    final int id = nextId++;

    }



    Now whenever you create a new instance of C, then its id will have a
    unique value. The Java-Compiler does not try to predict if you always
    assign the same value to a final instance variable, it will just
    produce the necessary code for the assignment, expecially it does not
    try to do such magic as with static finals as shown above.





    So back to your questions: Yes it makes sense to declare "constants" as
    static final. The JVM will not realize that an instance variable could
    actually be a class variable. It is your resposibility as programmer to
    tell the JVM if this is the case and you do so by declaring it as
    static. And yes AFAIK there is a difference between how constants of
    primitive types and object constants are treated, at least if they are
    static final. Static finals of primitive types are evaluated by the
    compiler and AFAIK static finals of object types are evaluated by the
    linker (i.e. during class-loading).



    cu



  • Thanks, for your response, eagle.

    I understand that the JVM will not realize that an instance variable could actually be a class variable. What I was asking is: If you know a "constant" instance variable will never/should never be accessed staticly (i.e., it's not a class variable), is there any reason to declare it static anyway?

    Though I must say that Chris has made me wonder if it ever makes sense, from a design point of view, to make private "constants" instance variables.

    Thanks again.


    Regards,
    Jack

    @eagle said:

    So back to your questions: Yes it makes sense to declare "constants" as static final. The JVM will not realize that an instance variable could actually be a class variable. It is your resposibility as programmer to tell the JVM if this is the case and you do so by declaring it as static. And yes AFAIK there is a difference between how constants of primitive types and object constants are treated, at least if they are static final. Static finals of primitive types are evaluated by the compiler and AFAIK static finals of object types are evaluated by the linker (i.e. during class-loading).

    cu



  • @PeaceLoveWTF said:





    Though I must say that Chris has
    made me wonder if it ever makes sense, from a design point of
    view, to make private "constants" instance variables.






    Well yes, that was my point, it makes sense, because otherwise all your instances will require more memory than necessary.



    Think of this:



    class AFiniteStateMachine {

    final int STATE_A = 1;

    final int STATE_B = 2;

    ...

    final int STATE_XYZ = 1000;



    int state = STATE_A;

    ...

    }



    Now, how much memory would you need for an instance of this class? And
    how much does it consume as it is defined? And how much does it consume
    after s/final/static final/ ?



    cu


Log in to reply