private final static attribute vs private final attribute

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?


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.