Why should data fields be static and final - java

Deitel's How To Program Java book says:
A final field should also be declared static if it is initialized in its declaration to a value.
Why is that?
public class A
{
private final int x = 5;
private static final int y = 5;
}
I think x and y are the same.
What does the static qualifier matter here?
What is the advantage of the static qualifier up there for software engineering observation?

x is an instance variable while y is global.
What does that mean?
Let's look at this example:
public class A {
public A() {
System.out.println("create A");
}
}
public class B {
public B() {
System.out.println("create B");
}
}
public class C {
private static B b = new B();
private A a = new A();
}
Then a main:
public static void main(String[] args) {
C c1 = new C();
C c2 = new C();
}
Which prints:
> create B
> create A
> create A
c1 and c2 shares the same instance of B while they both create their own instance of A!
So c1.b == c2.b while c1.a != c2.a.
So summary:
there is only one and the same place/address for field b for every instance of class C (c1, c2)
but for field a there are different places/addresses in the different instances.
The example is a bit oversized with class A and B:
Even for simple fields (int, float, ...) is one and the same place/occurrence for a static field in every instance of a class.

Since it is final, it will always hold the same value.
If you don't declare it static, you will create one variable for each instance of your class. Being static means you declare the variable only once, avoiding unnecessary memory usage.

Declaring a variable as static is more memory effecient. In your example for instance, no matter how many times you create a new A(), because fields x and fields y have been declared static, they will only be allocated memory once. If you do not declare them as static, they will be allocated memory with every new class instance.
It is sensible to declare a final variable that has been initialized like yours as static because it is not able to change, and thus allocating it memory just one time is acceptable.

Essentially, it's to save memory. If the constant is always the same no matter what, then you might as well make it static so that it doesn't get created for each object. You don't want to make it static, however, if the constant is not necessarily the same for each object (for example, if your constant is initialized somewhere in a constructor).

It saves memory as it only allocates for 1 copy of the variable. If you were to make a new instance for a non-static variable for it will make a new copy for that specified instance.
Since they are final they cannot be changed so it would make sense to make them static, so when you make new instances, nothing new is allocated for the variables since they can't even be altered.

Related

static object references and non static object references

What is the difference between the static object references and the non-static object references ?
class example{
int r =10;
void output(){
System.out.println("The value is "+r++);
}
}
public class Test{
static example q,w,e;
public static void main(String[] args) {
q = new example();
q.output();
w = new example();
w.output();
e = new example();
e.output();
example r,t,y;
r = new example();
r.output();
t = new example();
t.output();
y = new example();
y.output();
}
}
While running this code the output of this code is same .So the question arises that what is usage of declaring a static reference variable in code and what is the difference between these static and nonstatic reference variable in java.
A static variable can be accessed from other methods of the same class, or even from other classes (if it's public). The non static variables in your code a local variables, and they are only accessible to the main method, in which they are declared.
The output is the same since you call your output method each time for a difference instance of the example class. In each of them r is initialized to 10, so r++ returns 10.
This objects are bonded with class level. It will create the example q, w, e when your class loaded. Then objects will be assigned to p, q, w when you run the method. Then you can access that objects with class reference.
example.q or example.getq() //need to create getq static method
without creating Test object.
A static variable is shared within all instances of a class and will always remain the same, a non static variable is specific to a single instance of the class.
You are creating object of one class into another so which type of object you're creating will not affect to the value of instance. The JVM always return the same type of object with its instances.

What's the usage of static field in Java?

From the question What's the meaning of System.out.println in Java? I found that out in System.out.println is a static field.
From C/C++ background, it's easy to understand static method, as it's the same as function in C. However, I'm not sure the use case of static field.
Is it just a way to use multiple methods without instantiating an object just as we use System.out.println without instantiating anything? Or is there any use cases for static field?
static variables/methods not only have the property of being used without instantiation, but they are also consistent across multiple instances.
For example,
public class A {
public int a = 1;
public static int b = 2;
}
Now, when I do A a1 = new A() and A a2 = new A(), A.a gets 2x the memory and is stored in the object instance, while A.b gets the memory only once and is stored outside the instance.
A prime example of this would be
a1.b = 3;
System.out.println(a2.b);
This will print 3, instead of 2, because a1 changed the value of b for the whole class, and therefore, all the instances.
A static field is a property of the class, which gets allocated on the heap and is independent of a particular object instance.
You could use a static variable to count the number of instances of a class for example.
out is an object of PrintStream.
System is a class in java.lang package
println is an instance method(not a static method) of PrintStream class
To access the field out in System without instantiating System, the field is declared static.
The System class has only one instance of the OutputStream that writes to standard output (called out) so it's a static variable. We don't need more than one instance because there's only one standard output.
A static field, is a field that is set-up and can be get without instantiating a class (using new ClassName()).
For example:
public class MyClass {
public static int number = 1;
}
With the code above, you can get the "number" field using MyClass.number.
public class MyClass {
public int number = 1;
}
Now, you need to instantiate MyClass via constructor. Since there is no constructor declared, you just use new MyClass():
MyClass cl = new MyClass();
cl.number; // <-- The number
Static fields are also known as 'class' fields (as opposed to 'instance' fields).
That means that they are accessible without you needing to instantiate the class first.
So, you can call class methods (like Math.abs() on the Math class) without having to instantiate a Math class. You can also access properties like Math.PI.
Also, changing a class property means that it affects all instances of that class, meaning that every object that was instantiated will see this value change, allowing you to affect them with a single property change.
In addition to the .out var in System, it can either be used as a shared variable that all instances of a class can update
private static int meatballsConsumed;
Or as a general-purpose shared variable
public static String thisSeemsDangerous;
Or as a constant
public static final String FLD_OF_DREAMS = "COSTNER,KEVIN";

To class variable or not to class variable?

I got a class Foo having a method doSomething that uses two class-related variables b and c that are expensive to get/create. My first version looks like this:
public class Foo {
private final A a;
public Foo(A a) {
this.a = a;
}
public void doSomething() {
final B b = a.getB();
final C c = b.getC();
for (int i = 0; i < 1000; i++) {
// do something with b and c
}
}
}
So I get the first object (type B) via a class variable a and the second object (type C) via the first object.
Now, since those variables are related to the class and the method is always called exactly one time (though not necessarily when creating an object of type Foo), I thought about making them class variables as well:
public class Foo {
private final A a;
private final B b;
private final C c;
public Foo(A a) {
this.a = a;
b = a.getB();
c = b.getC();
}
public void doSomething() {
for (int i = 0; i < 1000; i++) {
// do something with b and c
}
}
}
I'm not sure which version to use if any of those two. I somehow don't feel comfortable making those two variables class members since they can be retrieved from the existing class variable a. However, it would increase readability of the methods IMO.
You are absolutely right. If it increases readability, bu all means do it. However, I would ask you this: What is the purpose of Referencing A from within the class? Is it only for getting B and C?
In this case, I would just input B and C in Foo's constructor!
This way you even make it more readable by breaking the dependency on A and Making the dependency on B and C more explicit.
Also, consider whether you are using these variables in other methods in the class. If the answer is yes- it signals that they should be class members, However, if the class contains a lot of methods that do not use these variables, that might signal the opposite.
The general principle you should follow here is the principle of High Cohesion
generally speaking, if you can use a local variable, it is preferable to using a field.
Using a local variable
limits the variable to where it is used.
uses less memory.
is thread safe.
Why not just store instances of B and C in your class Foo? Do you reference A somewhere in your class? Otherwise, Storing both B and C as instance variables is no less memory efficient, since storing one A object contains a B and C object.
From my experience static (or class variable|field|method) usually became evil after some time and needs to be refactorred out except cases when this stuff is static by it's nature (Math.PI or Math.max() are examples or such static things). If those methods are doing some computation based on anything dynamic I would leave them as instance.

Variable garbage collection in Java

Is there a difference between the following variable declarations?
Class A {
private int a;
A(){
a= 2;
}
}
VS
Class A {
private int a = 2;
A(){
}
}
Will garbage collection work any differently?
No there is no difference because the java compiler initialize "private int a = 2" inside the constructor internally. You can use java decompiler to confirm my above statement. So for both GC will work same.
There is no difference in the behaviour of your two initialisations. In the first example the a = 2 will happen just before the constructor code is called. If you made a final:
private final int a; //first example
private final int a = 2; //second example
Then you would see a difference between what you could do in the constructor:
A(){ //The blank final field a may not have been initialized for first example
}
A(){
a = 2; //The final field Apple.a cannot be assigned for second example
}
In both cases you are declaring int a as a member variable of the class. Whenever the class is instantiated, space will be set aside on the heap for that integer. However, the garbage collector only cares about whether or not there are any references to the containing object that has been instantiated. Regardless of what you do with the member variables, the object will stay in memory if there is a reference to it, after which point it's eligible for garbage collection.
However, perhaps you believe there should be a difference? Why is that?

Do final (constant) instance (non-static) variables act like class (static) variables?

In the following example, the variable b is declared final, but not static. That means it's a constant instance variable. However, because it's constant, none of the Passenger objects can change its value. So isn't it better to declare it static and make it a class variable, so that there is only one copy to be used by all instantiated objects?
class Passenger {
int a;
final int b = 0;
void drive() {
System.out.println("I'm driving!");
}
}
The purpose of final but non-static variables is to have an object-wide constant. It should be initialized in the constructor:
class Passenger {
final int b;
Passenger(int b) {
this.b = b;
}
}
If you are always assigning a constant literal value (0) to the final variable, it doesn't make much sense. Using static is preferred so that you are only having a single copy of b:
static final int b = 0;
BTW I don't think having default access modifier was your intention.
It depends on the purpose of b. Usually constants are there for a specific purpose. If you make it static you could accidentally change it in some instance of that class and that will affect all the others.
If you have multiple instances of Passenger class, I would go for making it static. While this has little benefit when talking about an int variable, this could save some memory if you have complex objects. This is because a static variable belongs to a class, not to an instance, thus memory space for it will be reserved only once, and it will be referred by the class object itself, not by the instances. Of course, you should be aware that having b as a static variable means that the changes made on this variable will be reflected on all the classes that access this variable, but since you made it final this won't be the case.
Note also that with the code you've written, classes in the same package as Passenger will be able to read the b value by accessing it via Passenger.b (if static).
In java, the static attribute basically means: associated with the type itself, rather than an instance of the type.
In other words you can reference a static variable without creating instances of that type... Whereas in the case of just using final you'd need to instantiate the class.
So, yes, to answer your question, I'd say that you're right. :)
A final primitive is the same as a static final primitive (except more efficient)
A final reference to an immutable object the same as a static final reference of the same.
A final reference to a mutable object is NOT the same as a static final reference of the same.
final int i = 0;
// same as
static final int = 0;
final String hi = "Hello";
// same as
static final String hi = "Hello";
final List<String> list = new ArrayList<String>();
// is NOT the same as
static final List<String> list = new ArrayList<String>();
The only time the last example is the same is when you have a singleton. It is fairly common for singletons to be written with a confusion of static and non static fields and methods as the difference is not obvious. :|
A final variable is defined when you need a constant, so you can assign a value just once.
Using static, instead, you are defining a variable shared by all the objects of that type (like a global variable) and it is not associated with a certain object itself.

Categories