private final static attribute vs private final attribute

359,026

Solution 1

In general, static means "associated with the type itself, rather than an instance of the type."

That means you can reference a static variable without having ever created an instances of the type, and any code referring to the variable is referring to the exact same data. Compare this with an instance variable: in that case, there's one independent version of the variable per instance of the class. So for example:

Test x = new Test();
Test y = new Test();
x.instanceVariable = 10;
y.instanceVariable = 20;
System.out.println(x.instanceVariable);

prints out 10: y.instanceVariable and x.instanceVariable are separate, because x and y refer to different objects.

You can refer to static members via references, although it's a bad idea to do so. If we did:

Test x = new Test();
Test y = new Test();
x.staticVariable = 10;
y.staticVariable = 20;
System.out.println(x.staticVariable);

then that would print out 20 - there's only one variable, not one per instance. It would have been clearer to write this as:

Test x = new Test();
Test y = new Test();
Test.staticVariable = 10;
Test.staticVariable = 20;
System.out.println(Test.staticVariable);

That makes the behaviour much more obvious. Modern IDEs will usually suggest changing the second listing into the third.

There is no reason to have an inline declaration initializing the value like the following, as each instance will have its own NUMBER but always with the same value (is immutable and initialized with a literal). This is the same than to have only one final static variable for all instances.

private final int NUMBER = 10;

Therefore if it cannot change, there is no point having one copy per instance.

But, it makes sense if is initialized in a constructor like this:

// No initialization when is declared
private final int number;

public MyClass(int n) {
   // The variable can be assigned in the constructor, but then
   // not modified later.
   number = n;
}

Now, for each instance of MyClass, we can have a different but immutable value of number.

Solution 2

A static variable stays in the memory for the entire lifetime of the application, and is initialised during class loading. A non-static variable is being initialised each time you construct a new object. It's generally better to use:

private static final int NUMBER = 10;

Why? This reduces the memory footprint per instance. It possibly is also favourable for cache hits. And it just makes sense: static should be used for things that are shared across all instances (a.k.a. objects) of a certain type (a.k.a. class).

Solution 3

For final, it can be assigned different values at runtime when initialized. For example

class Test{
  public final int a;
}

Test t1  = new Test();
t1.a = 10;
Test t2  = new Test();
t2.a = 20; //fixed

Thus each instance has different value of field a.

For static final, all instances share the same value, and can't be altered after first initialized.

class TestStatic{
      public static final int a = 0;
}

TestStatic t1  = new TestStatic();
t1.a = 10; // ERROR, CAN'T BE ALTERED AFTER THE FIRST 
TestStatic t2  = new TestStatic();
t1.a = 20;   // ERROR, CAN'T BE ALTERED AFTER THE FIRST INITIALIZATION.

Solution 4

static means "associated with the class"; without it, the variable is associated with each instance of the class. If it's static, that means you'll have only one in memory; if not, you'll have one for each instance you create. static means the variable will remain in memory for as long as the class is loaded; without it, the variable can be gc'd when its instance is.

Solution 5

Reading the answers I found no real test really getting to the point. Here are my 2 cents :

public class ConstTest
{

    private final int         value             = 10;
    private static final int  valueStatic       = 20;
    private final File        valueObject       = new File("");
    private static final File valueObjectStatic = new File("");

    public void printAddresses() {


        System.out.println("final int address " +
                ObjectUtils.identityToString(value));
        System.out.println("final static int address " +
                ObjectUtils.identityToString(valueStatic));
        System.out.println("final file address " + 
                ObjectUtils.identityToString(valueObject));
        System.out.println("final static file address " + 
                ObjectUtils.identityToString(valueObjectStatic));
    }


    public static void main(final String args[]) {


        final ConstTest firstObj = new ConstTest();
        final ConstTest sndObj = new ConstTest();

        firstObj.printAdresses();
        sndObj.printAdresses();
    }

}

Results for first object :

final int address java.lang.Integer@6d9efb05
final static int address java.lang.Integer@60723d7c
final file address java.io.File@6c22c95b
final static file address java.io.File@5fd1acd3

Results for 2nd object :

final int address java.lang.Integer@6d9efb05
final static int address java.lang.Integer@60723d7c
final file address java.io.File@3ea981ca
final static file address java.io.File@5fd1acd3

Conclusion :

As I thought java makes a difference between primitive and other types. Primitive types in Java are always "cached", same for strings literals (not new String objects), so no difference between static and non-static members.

However there is a memory duplication for non-static members if they are not instance of a primitive type.

Changing value of valueStatic to 10 will even go further as Java will give the same addresses to the two int variables.

Share:
359,026
Admin
Author by

Admin

Updated on November 18, 2020

Comments

  • Admin
    Admin over 3 years

    In Java, what's the difference between:

    private final static int NUMBER = 10;
    

    and

    private final int NUMBER = 10;
    

    Both are private and final, the difference is the static attribute.

    What's better? And why?

  • bobby
    bobby almost 15 years
    a static variable is also created at runtime. Therefore you can use said variable or method before the object is created.
  • Vineet Reynolds
    Vineet Reynolds almost 15 years
    Until enums were available in Java 5, static final was the usual way of declaring constants.
  • Chii
    Chii almost 15 years
    @Vineet: static finals are still the way to declare primitive constants, unless you have an enumerated number of them =)
  • starblue
    starblue almost 15 years
    By Java coding convention the name of a static final variable should be all uppercase.
  • user unknown
    user unknown over 12 years
    Please don't just repeat, what other answers have already covered.
  • ataulm
    ataulm over 11 years
    Static methods wouldn't be required to access static variables - I think you're thinking of "accessing instance variables from static methods" (not-allowed).
  • Jon Skeet
    Jon Skeet over 11 years
    @Matthew: Potentially. Not for a constant, but for some logically instance-related value. Not that I like singletons much anyway.
  • MattC
    MattC about 11 years
    This will not compile! A final variable must either be assigned a value, or have a value assigned in its constructors. This answer would be correct if 2 constructors were given, with each assigning 'a' to a different value.
  • Win Myo Htet
    Win Myo Htet about 11 years
    A radical question. Is it worth using private final over private static final to squeeze out/reclaim that little memory from the class? Let's say for the calculator device with limited ram but plenty of CPU resources.
  • Jon Skeet
    Jon Skeet about 11 years
    @WinMyoHtet: If you use a static field, there's only one in total. If you use an instance field, there's one per instance. Using a static field is going to be better unless you don't have any instances, in which case it's useless anyway.
  • Win Myo Htet
    Win Myo Htet about 11 years
    @Jon True. However, The use case I am talking about is the Android Activity(UI screen) instance. Depending on the design, the number of instances will vary but usually the number of instances of single activity will be around 2-4. Let's say we have a screen Density property which need to be calculated for each Activity, we can calculate one and make it static or we can make it non static, thus, we can calculate it every time but we can reclaim that memory when the Activity is finish. Or is this approach premature optimization ?
  • sanz
    sanz over 10 years
    for inner classes, you cannot use private static final
  • Jon Skeet
    Jon Skeet over 10 years
    @sanz: You can for constant declarations. So private static final int FOO = 10; is fine even in an inner class.
  • sanz
    sanz over 10 years
    @JonSkeet I believe it's possible only for primitive types. Not for private static final Integer FOO = 10;
  • Jon Skeet
    Jon Skeet over 10 years
    @sanz: Primitives and strings, yes.
  • Dharmendra
    Dharmendra about 10 years
    @JonSkeet If I have 50 Activity classes in the app, In each activity I have one "private static final string" variables. so all will be gets memory when app starts. but in Android we do not have multiple instances of Activity class and we do not know whether user will go through all the activities. so its memory waste. so in this scenario if we keep just "Private final String" then it will allocate memory to only those activity classes which user opens. Please explain better solutions and your understanding.
  • Jon Skeet
    Jon Skeet about 10 years
    @Dharmendra: Do you really think that 50 variables is going to be significant? Are all those activity classes even going to be loaded? Is the variable logically part of the state of the class itself, or of an instance of the class?
  • Dharmendra
    Dharmendra about 10 years
    @JonSkeet I am taking one variable "Tag" which is private static final for print something in the class for ex. Log.e(Tag, "Hello"). Here Tag is our variable. it is important to each class inorder to identify "Hello" for each class(Different classes not same type). There is no possibility that all those activity will be loaded. This Tag variable is the state of the class instead of instance of the class.
  • Jon Skeet
    Jon Skeet about 10 years
    Well if the activity class isn't loaded, the variable won't be initialized either. Again though, it sounds like you're really worrying over nothing anyway.
  • Dharmendra
    Dharmendra about 10 years
    So you mean private static variable will get memory when class will loads, not at a time when application initialized(but class not loaded)?
  • Jon Skeet
    Jon Skeet about 10 years
    @Dharmendra: Yes - if the class hasn't been loaded, there's no need for a variable. This is somewhat offtopic for this thread now. If you have more questions, I suggest you ask on a new post - but again, I would strongly encourage you to consider whether the cost of one variable per class is a problem even if all the classes are loaded.
  • Rudi Kershaw
    Rudi Kershaw almost 10 years
    Confirming, this will not compile. As expressed above, final instance variable's must be instantiated before the constructor finishes, and final class variables must be instantiated before the class has been created (you can use a static block). Why has this got so many upvotes?
  • jamesdeath123
    jamesdeath123 over 9 years
    as MattC pointed out, you cannot assign to a final variable after creating that object - in fact, you cannot even create an object without giving values to its final variables...
  • dkneller
    dkneller about 9 years
    Autoboxing of the 'int' -> Integer is causing confusion here. You're seeing that autoboxing of some (small) int values leads to the same Integer object.
  • BlondCode
    BlondCode almost 9 years
    I had a link here for a detailed comparison. I am sorry guys, this has been moderated i guess.
  • Faz
    Faz almost 9 years
    Just in case anyone stumbles on this, please follow MattC's answer.
  • mikus
    mikus over 8 years
    sure its a answer for this quesiton?
  • Salsero69
    Salsero69 over 8 years
    This is what I think the OP was asking, I had forgotten that finals can be assigned a value at instantiation if it wasn't provided one at declaration.
  • Erick G. Hagstrom
    Erick G. Hagstrom over 8 years
    The link is back. An editor had taken it out as dead. It seems to be live now.
  • Ruchir Baronia
    Ruchir Baronia over 8 years
    Instance variables get gc'd whenever all references/objects to it die, right?
  • duffymo
    duffymo over 8 years
    Instances are gc'd, but statics are associated with classes, not instances. As long as the class remains in memory you'll be able to refer to its public static instances and methods. Those go into perm gen (or whatever its JDK 8 equivalent is) and aren't gc'd.
  • duffymo
    duffymo over 8 years
    Wrong. If you have a reference to an instance in memory you can access its available methods and instances. The rest is wrong. You fail to understand the difference between a class and its instances.
  • bond
    bond over 8 years
    @JonSkeet - yes - don't do it unless if you want to optimize out the memory lookup for the static version (if it cannot be inline). If you have runtime-generated finals that cannot be optimized at the compiler then you can save yourself a lot of memory lookups by copying the variable into the instance.
  • Daniel
    Daniel about 8 years
    Could you please elaborate on which is better and why?
  • Maggyero
    Maggyero over 7 years
    @JonSkeet: "There is no reason to have a declaration such as private final int NUMBER = 10; If it cannot change, there is no point having one copy per instance." What about this (a person cannot change name but each person has his own name)? class Person { private final String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public void setAge(int age) { this.age = age; } }
  • Jon Skeet
    Jon Skeet over 7 years
    @Maggyero: Then that's an entirely different situation - it's not a constant value which will be the same for all instances, unlike private final int NUMBER = 10;
  • Maggyero
    Maggyero over 7 years
    @JonSkeet: Alright, I thought your statement was general, not particular to that situation, hence my question. Maybe you could edit the answer to make that clear, so that other people are not confused.
  • MANN
    MANN almost 7 years
    @Martijn Courteaux, how about a situation where a class will be used once during the lifetime of the app! private final int will be removed from memory when the instance will be GC'ed whereas private static final int will remain in memory throughout the lifespan of that app. What do you suggest in the above scenario?
  • Martijn Courteaux
    Martijn Courteaux almost 7 years
    @StackHola @dkneller Indeed, autoboxing is a very important detail that happens here. The signature is ObjectUtils.identityToString(Object). (Besides, Java has no pass by reference anyways). A real useful test would be to allocate two objects and change the value of a public final int FOO = 10 variable using Java reflections in a forced way. Then check if the other object has also changed its value.
  • Martijn Courteaux
    Martijn Courteaux almost 7 years
    @MANN: This is highly theoretical. There is literally no useful use case scenario for that. This could be beneficial if you have like 50000 int vars in a class. Even in this case, this would save up 200kb of memory. Since we are talking Java, this seems totally irrelevant. In case of memory critical devices, a decent C or C++ compiler would inline those integer values always, eliminating the need for freeing up memory completely.
  • Manish Kumar Sharma
    Manish Kumar Sharma almost 5 years
    Please DELETE this answer
  • Jon Skeet
    Jon Skeet over 4 years
    @Mark: When the final field already has an initializer, it can't be assigned a different value in the constructor. And the value 10 is a compile-time constant. So you've got a field per instance, but every field is guaranteed to have the same constant value. What's the benefit of that over having a single static field? (I can just about imagine some reflection-based scenarios, but that's all.)
  • Mark
    Mark over 4 years
    @JonSkeet you're totally correct, it's my bad. An inline declaration like this has no sense for a private final, as it will have always the same value for all instances (which is the same than to have a single static variable for all instances). It makes sense if the final is initialized in the constructor and the initial value can be different, therefore you might have a different variable with different values in different instances. I'll delete the comment soon. May be you can specify that in the answer....
  • ishallwin
    ishallwin over 3 years
    I agree. The answer should be deleted. I came to this answer via a Medium article which said final variables can be altered via their objects.
  • zhangxaochen
    zhangxaochen over 2 years
    error: cannot assign a value to final variable a