There are two classes, each with it's own static field. What will happen when one field depends on another? For example:
public class A {
public final static Something something = new Something(B.needed);
}
public class B {
public final static Needed needed = new Needed();
}
Test I made suggest that in that case needed
will be initialized before something
. In test I was asking Java for variable of class A
and B
wasn't loaded before. However, result may be just coincidence. Is there any mechanism in Java that will guarantee me that needed
will always initialize to be used as argument?
I made another test. Results also show that in extreme cases final primitive types have default value (so they actually have different values in different places of code, despite being final):
public class A {
public final static int test = 3 - B.test;
}
public class B {
public final static int test = 2 - A.test;
}
If you run test in a way that loads class A
first, values will be:
A.test = 1
B.test = 2
Then if you run test with B
loading first, values will be:
A.test = 3
B.test = -1
It seems that Java simply uses default int
value 0
. I was surprised that this code compiles.
Results of second test also suggest that Java tries to initialize static field it's planning to use when initializing variable from other class. Is this correct? Is it documented, predictable behavior?
One advantage is the ability to share data between instances of a class by using static variables. However, static variables will be shared between instances of the same class within a JVM, but not across JVMs. You'll need to plan accordingly.
Static variables are indeed shared between threads, but the changes made in one thread may not be visible to another thread immediately, making it seem like there are two copies of the variable.
A static variable is shared by all instances of a class. Only one variable created for the class.
Static variables are generally considered bad because they represent global state and are therefore much more difficult to reason about. In particular, they break the assumptions of object-oriented programming.
As long as you have tree-like dependencies of your classes, you can rely on class X having been initialized when class Y needs it. As soon as you introduce loops (class X needs Y and Y needs X, or even A needs B which needs C which needs D which needs A), behaviour is undefined, and may change whenever you change your java version, JVM vendor, hardware platform or whatever. Don't do that - circular dependencies are almost always the result of bad planning.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With