ChatGPT解决这个技术问题 Extra ChatGPT

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?

private final static -> create this variable only once. private final -> create this variable for every object. First one saves memory, go for it.
final static means this variable is a constant and only associates with the class itself, i.e. "one constant variable per class" while final means "one constant variable per instance". As a result, you cannot put a final static variable in the class' constructor since the constructor involves in new an instance. (You can try it yourself and will get an error)
By "cannot put a final static variable in the class' constructor" I mean one cannot initialize a final static variable in the constructor, the only way is to use a static initializer :)
@user1923551 The effect is inversed for stuff that is only needed for a limited amounts of time in big applications, in memory scarce applications or when using a singleton. Having static stuff in every class will reserve a (huge) chunk of memory for stuff that isn't needed. It can also be a memory leak to declare static final objects or collections.

J
Jon Skeet

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.


Until enums were available in Java 5, static final was the usual way of declaring constants.
@Vineet: static finals are still the way to declare primitive constants, unless you have an enumerated number of them =)
@Matthew: Potentially. Not for a constant, but for some logically instance-related value. Not that I like singletons much anyway.
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.
@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.
M
Martijn Courteaux

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).


a static variable is also created at runtime. Therefore you can use said variable or method before the object is created.
By Java coding convention the name of a static final variable should be all uppercase.
@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?
@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.
l
lucas

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.

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.
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?
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...
Just in case anyone stumbles on this, please follow MattC's answer.
Please DELETE this answer
d
duffymo

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.


Instance variables get gc'd whenever all references/objects to it die, right?
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.
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.
S
StackHola

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.


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.
@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.
M
Michiel

While the other answers seem to make it pretty clear that there is generally no reason to use non-static constants, I couldn't find anyone pointing out that it is possible to have various instances with different values on their constant variables.

Consider the following example:

public class TestClass {
    private final static double NUMBER = Math.random();

    public TestClass () {
        System.out.println(NUMBER);
    }
}

Creating three instances of TestClass would print the same random value three times, since only one value is generated and stored into the static constant.

However, when trying the following example instead:

public class TestClass {
    private final double NUMBER = Math.random();

    public TestClass () {
        System.out.println(NUMBER);
    }
}

Creating three instances of TestClass would now print three different random values, because each instance has its own randomly generated constant value.

I can't think of any situation where it would be really useful to have different constant values on different instances, but I hope this helps pointing out that there is a clear difference between static and non-static finals.


D
DigitalRoss

very little, and static

There isn't much difference as they are both constants. For most class data objects, static would mean something associated with the class itself, there being only one copy no matter how many objects were created with new.

Since it is a constant, it may not actually be stored in either the class or in an instance, but the compiler still isn't going to let you access instance objects from a static method, even if it knows what they would be. The existence of the reflection API may also require some pointless work if you don't make it static.


N
Novitzky

As already Jon said, a static variable, also referred to as a class variable, is a variable which exists across instances of a class.

I found an example of this here:

public class StaticVariable
{
  static int noOfInstances;
  StaticVariable()
  {
    noOfInstances++;
  }
  public static void main(String[] args)
  {
    StaticVariable sv1 = new StaticVariable();
    System.out.println("No. of instances for sv1 : " + sv1.noOfInstances);

    StaticVariable sv2 = new StaticVariable();
    System.out.println("No. of instances for sv1 : "  + sv1.noOfInstances);
    System.out.println("No. of instances for st2 : "  + sv2.noOfInstances);

    StaticVariable sv3 = new StaticVariable();
    System.out.println("No. of instances for sv1 : "  + sv1.noOfInstances);
    System.out.println("No. of instances for sv2 : "  + sv2.noOfInstances);
    System.out.println("No. of instances for sv3 : "  + sv3.noOfInstances);
  }
}

Output of the program is given below:

As we can see in this example each object has its own copy of class variable.

C:\java>java StaticVariable
No. of instances for sv1 : 1
No. of instances for sv1 : 2
No. of instances for st2 : 2
No. of instances for sv1 : 3
No. of instances for sv2 : 3
No. of instances for sv3 : 3

V
Volker Stolz

From the tests i have made, static final variables are not the same with final(non-static) variables! Final(non-static) variables can differ from object to object!!! But that's only if the initialization is made within the constructor! (If it is not initialized from the constructor then it is only a waste of memory as it creates final variables for every object that is created that cannot be altered.)

For example:

class A
{
    final int f;
    static final int sf = 5;

    A(int num)
    {
        this.f = num;
    }

    void show()
    {
        System.out.printf("About Object: %s\n Final: %d\n Static Final: %d\n\n", this.toString(), this.f, sf);
    }

    public static void main(String[] args)
    {
        A ob1 = new A(14);
        ob1.show();

        A ob2 = new A(21);
        ob2.show();

    }
}

What shows up on screen is:

About Object: A@addbf1 Final: 14 Static Final: 5

About Object: A@530daa Final: 21 Static Final: 5

Anonymous 1st year IT student, Greece


E
Erick G. Hagstrom

Furthermore to Jon's answer if you use static final it will behave as a kind-of "definition". Once you compile the class which uses it, it will be in the compiled .class file burnt. Check my thread about it here.

For your main goal: If you don't use the NUMBER differently in the different instances of the class i would advise to use final and static. (You just have to keep in mind to not to copy compiled class files without considering possible troubles like the one my case study describes. Most of the cases this does not occur, don't worry :) )

To show you how to use different values in instances check this code:

public class JustFinalAttr {
  public final int Number;

  public JustFinalAttr(int a){
    Number=a;
  }
}

...System.out.println(new JustFinalAttr(4).Number);

I had a link here for a detailed comparison. I am sorry guys, this has been moderated i guess.
The link is back. An editor had taken it out as dead. It seems to be live now.
A
Adrian

Here is my two cents:

final           String CENT_1 = new Random().nextInt(2) == 0 ? "HEADS" : "TAILS";
final   static  String CENT_2 = new Random().nextInt(2) == 0 ? "HEADS" : "TAILS";

Example:

package test;

public class Test {

    final long OBJECT_ID = new Random().nextLong();
    final static long CLASSS_ID = new Random().nextLong();

    public static void main(String[] args) {
        Test[] test = new Test[5];
        for (int i = 0; i < test.length; i++){
            test[i] = new Test();
            System.out.println("Class id: "+test[i].CLASSS_ID);//<- Always the same value
            System.out.println("Object id: "+test[i].OBJECT_ID);//<- Always different
        }
    }
}

The key is that variables and functions can return different values.Therefore final variables can be assigned with different values.


Could you please elaborate on which is better and why?
V
Vaibs

Just Another simple example to understand the usage of static, static final, final variables. Code comments have the proper explanation.

public class City {

    // base price that is always same for all objects[For all cities].
    private static double iphone_base_price = 10000;

    // this is total price = iphone_base_price+iphone_diff;
    private double iphone_citi_price;

    // extra price added to iphone_base_price. It is constant per city. Every
    // city has its own difference defined,
    private final double iphone_diff;

    private String cityName = "";

    // static final will be accessible everywhere within the class but cant be
    // changed once initialized.
    private static final String countryName = "India";

    public City(String cityName, double iphone_diff) {
        super();
        this.iphone_diff = iphone_diff;
        iphone_citi_price = iphone_base_price + iphone_diff;
        this.cityName = cityName;

    }

    /**
     * get phone price
     * 
     * @return
     */
    private double getPrice() {

        return iphone_citi_price;
    }

    /**
     * Get city name
     * 
     * @return
     */
    private String getCityName() {

        return cityName;
    }

    public static void main(String[] args) {

        // 300 is the
        City newyork = new City("Newyork", 300);
        System.out.println(newyork.getPrice() + "  " + newyork.getCityName());

        City california = new City("California", 800);
        System.out.println(california.getPrice() + "  " + california.getCityName());

        // We cant write below statement as a final variable can not be
        // reassigned
        // california.iphone_diff=1000; //************************

        // base price is defined for a class and not per instances.
        // For any number of object creation, static variable's value would be the same
        // for all instances until and unless changed.
        // Also it is accessible anywhere inside a class.
        iphone_base_price = 9000;

        City delhi = new City("delhi", 400);
        System.out.println(delhi.getPrice() + "  " + delhi.getCityName());

        City moscow = new City("delhi", 500);
        System.out.println(moscow.getPrice() + "  " + moscow.getCityName());

        // Here countryName is accessible as it is static but we can not change it as it is final as well. 
        //Something are meant to be accessible with no permission to modify it. 
        //Try un-commenting below statements
        System.out.println(countryName);

        // countryName="INDIA";
        // System.out.println(countryName);

    }

}

N
NarekOnLine

Since a variable in a class is declared as final AND initialised in the same command, there is absolutely no reason to not declare it as static, since it will have the same value no matter the instance. So, all instances can share the same memory address for a value, thus saving processing time by eliminating the need to create a new variable for each instance and saving memory by sharing 1 common address.


D
DanielBarbarian

private static final will be considered as constant and the constant can be accessed within this class only. Since, the keyword static included, the value will be constant for all the objects of the class.

private final variable value will be like constant per object.

You can refer the java.lang.String or look for the example below.

public final class Foo
{

    private final int i;
    private static final int j=20;

    public Foo(int val){
        this.i=val;
    }

    public static void main(String[] args) {
        Foo foo1= new Foo(10);

        Foo foo2= new Foo(40);

        System.out.println(foo1.i);
        System.out.println(foo2.i);
        System.out.println(check.j);
    }
}

//Output:

10
40
20

O
Omar Al-Ithawi

The static one is the same member on all of the class instances and the class itself. The non-static is one for every instance (object), so in your exact case it's a waste of memory if you don't put static.


S
Sanjay

If you mark this variable static then as you know, you would be requiring static methods to again access these values,this will be useful if you already think of using these variables only in static methods. If this is so then this would be the best one.

You can however make the variable now as public since no one can modify it just like "System.out", it again depends upon your intentions and what you want to achieve.


Static methods wouldn't be required to access static variables - I think you're thinking of "accessing instance variables from static methods" (not-allowed).
r
rommel

Lets say if the class will not have more than one instance ever, then which one takes more memory:

private static final int ID = 250; or private final int ID = 250;

I've understood that static will refer to the class type with only one copy in the memory and non static will be in a new memory location for each instance variable. However internally if we just compare 1 instance of the same class ever (i.e. more than 1 instance would not be created), then is there any overhead in terms of space used by 1 static final variable?


Please don't just repeat, what other answers have already covered.
T
Tsasaa

Static variable belongs to the class (which means all the objects share that variable). Non static variable belongs to each objects.

public class ExperimentFinal {

private final int a;
private static final int b = 999; 

public ExperimentFinal(int a) {
    super();
    this.a = a;
}
public int getA() {
    return a;
}
public int getB() {
    return b;
}
public void print(int a, int b) {
    System.out.println("final int: " + a + " \nstatic final int: " + b);
}
public static void main(String[] args) {
    ExperimentFinal test = new ExperimentFinal(9);
    test.print(test.getA(), test.getB());
} }

As you can see above example, for "final int" we can assign our variable for each instance (object) of the class, however for "static final int", we should assign a variable in the class (static variable belongs to the class).


W
Warren Jennings

If you use static the value of the variable will be the same throughout all of your instances, if changed in one instance the others will change too.


H
Hashem Alhariry

Final: Once a final variable has been assigned, it always contains the same value. wherever the variable is static or not static: it will be only one variable for all instances initialized one time in Memory


Y
YoungHobbit

This might help

public class LengthDemo {
public static void main(String[] args) {
    Rectangle box = new Rectangle();
    System.out.println("Sending the value 10.0 "
            + "to the setLength method.");
    box.setLength(10.0);
    System.out.println("Done.");
    }
}

sure its a answer for this quesiton?
U
Uzma Nasir

"Static" keyword makes the variable property of the class rather than individual instances of the class. There will be one copy of that variable that is shared amongst all the instances of that class. Any change in the state of the static variable will be reflected across all the instances. Add final to static and we get a variable that has been initialised once and for all at the class loading time and cannot be changed later by any instance of the class. Static final variables need to be initialised at the declaration time else we have compile time error. As far as private instance field is concerned, it refers to the property /state of an object /instance of a class. Each instance /object of the class will have its own copy of instance variable. When instance variable is declared final, it means we cannot change its value for this instance. For this we need to initialise the final variable either at declaration or in the constructor.If its not done in either of them, compile time error will show. Once initialised, if you try to reassign a value you will get a compile time error. Use static final variables where the data will be shared across all the instances of the class and you want the data to be read only.Use instance final variable if you want to represent some data that belongs to a each individual instance of the class but once stored cannot be changed. Usage of static and instance key word depends upon your design needs and what that data represents in the domain. If the data is used across the class instances then there is no need for individual copies/memory references for each object.