How does the static modifier affect this code? - java

Here is my code:
class A {
static A obj = new A();
static int num1;
static int num2=0;
private A() {
num1++;
num2++;
}
public static A getInstance() {
return obj;
}
}
public class Main{
public static void main(String[] arg) {
A obj = A.getInstance();
System.out.println(obj.num1);
System.out.println(obj.num2);
}
}
The output is 1 0, but I can't understand.
Can somebody explain it to me?

In Java two phases take place: 1. Identification, 2. Execution
In identification phase all static variables are detected and initialized with default values.
So now the values are:
A obj=null
num1=0
num2=0
The second phase, execution, starts from top to bottom. In Java, the execution starts from the first static members.
Here your first static variable is static A obj = new A();, so first it will create the object of that variable and call the constructor, hence the value of num1 and num2 becomes 1.
And then, again, static int num2=0; will be executed, which makes num2 = 0;.
Now, suppose your constructor is like this:
private A(){
num1++;
num2++;
System.out.println(obj.toString());
}
This will throw a NullPointerException as obj still has not got a reference of class A.

What the static modifier means when applied to a variable declaration is that the variable is a class variable rather than an instance variable. In other words ... there is only one num1 variable, and only one num2 variable.
(Aside: a static variable is like a global variable in some other languages, except that its name is not visible everywhere. Even if it is declared as a public static, the unqualified name is only visible if it is declared in the current class or a superclass, or if it is imported using a static import. That's the distinction. A true global is visible without qualification anywhere.)
So when you refer to obj.num1 and obj.num2, you are actually referring to the static variables whose real designations are A.num1 and A.num2. And similarly, when the constructor increments num1 and num2, it is incrementing the same variables (respectively).
The confusing wrinkle in your example is in the class initialization. A class is initialized by first default initializing all of the static variables, and then executing the declared static initializers (and static initializer blocks) in the order that they appear in the class. In this case, you have this:
static A obj = new A();
static int num1;
static int num2=0;
It happens like this:
The statics start out with their default initial values; A.obj is null and A.num1 / A.num2 are zero.
The first declaration (A.obj) creates an instance of A(), and the constructor for A increments A.num1 and A.num2. When the declaration completes, A.num1 and A.num2 are both 1, and A.obj refers to the newly constructed A instance.
The second declaration (A.num1) has no initializer, so A.num1 doesn't change.
The third declaration (A.num2) has an initializer that assigns zero to A.num2.
Thus, at the end of the class initialization, A.num1 is 1 and A.num2 is 0 ... and that's what your print statements show.
This confusing behaviour is really down to the fact that you are creating an instance before the static initialization has completed, and that the constructor you are using depends on and modifies a static that is yet to be initialized. This something that you should avoid doing in real code.

1,0 is correct.
When the class is loaded all static data is initialized in oder they are declared. By default int is 0.
first A is created. num1 and num2 becoming 1 and 1
than static int num1; does nothing
than static int num2=0; this writes 0 to num2

It is due to the order of the static initializers. Static expressions in classes are evaluated in a top-down order.
The first to be called is the constructor of A, which sets num1 and num2 both to 1:
static A obj = new A();
Then,
static int num2=0;
is called and sets num2=0 again.
That is why num1 is 1 and num2 is 0.
As a side note, a constructor should not modify static variables, that is very bad design. Instead, try a different approach to implementing a Singleton in Java.

A section in JLS can be found: §12.4.2.
Detailed Initialization Procedure:
9.Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface,
in textual order, as though they were a single block, except that
final class variables and fields of interfaces whose values are
compile-time constants are initialized first
So the three static variable will be initialized one by one in textual order.
So
static A obj = new A();
//num1 = 1, num2 = 1;
static int num1;
//this is initilized first, see below.
static int num2=0;
//num1 = 1, num2 = 0;
If I change the order to:
static int num1;
static int num2=0;
static A obj = new A();
The result will be 1,1.
Note that the static int num1; is not a variable initializer because(§8.3.2):
If a field declarator contains a variable initializer, then it has the
semantics of an assignment (§15.26) to the declared variable, and: If
the declarator is for a class variable (that is, a static field), then
the variable initializer is evaluated and the assignment performed
exactly once, when the class is initialized
And this class variable is initialized when the class is created. This happens first(§4.12.5).
Every variable in a program must have a value before its value is
used: Each class variable, instance variable, or array component is
initialized with a default value when it is created (§15.9, §15.10):
For type byte, the default value is zero, that is, the value of
(byte)0. For type short, the default value is zero, that is, the value
of (short)0. For type int, the default value is zero, that is, 0. For
type long, the default value is zero, that is, 0L. For type float, the
default value is positive zero, that is, 0.0f. For type double, the
default value is positive zero, that is, 0.0d. For type char, the
default value is the null character, that is, '\u0000'. For type
boolean, the default value is false. For all reference types (§4.3),
the default value is null.

Maybe it will help to think of it in this way.
Classes are blueprints for objects.
Objects can have variables when they are instantiated.
Classes can also have variables. These are declared as static. So they are set on the class rather than the object instances.
You can only every have one of any class in an application so it's kind of like global storage specifically for that class. These static variables can of course be accessed and modified from anywhere in your application (assuming they are public).
Here is and example of a "Dog" class that uses static variable to track the number of instances it has created.
"Dog" class is the cloud while the Orange boxes are "Dog" instances.
read more
Hope this helps!
If you feel like some trivia, this idea was first introduced by Plato

The static keyword is used in java mainly for memory management. We may apply static keyword with variables, methods, blocks and nested class. The static keyword belongs to the class than instance of the class.For brief explanation about static keyword :
http://www.javatpoint.com/static-keyword-in-java

Many of the answers above are correct. But really to illustrate what is happening I've made some small modifications below.
As mentioned multiple times above, what's happening is a instance of class A is being created before class A is fully loaded. So what is considered the normal 'behavior' is not observed. This is not too dissimilar to calling methods from a constructor that can be overridden. In that case, instance variables may not be in an intuitive state. In this example class variables are not in an intuitive state.
class A {
static A obj = new A();
static int num1;
static int num2;
static {
System.out.println("Setting num2 to 0");
num2 = 0;
}
private A() {
System.out.println("Constructing singleton instance of A");
num1++;
num2++;
}
public static A getInstance() {
return obj;
}
}
public class Main {
public static void main(String[] arg) {
A obj = A.getInstance();
System.out.println(obj.num1);
System.out.println(obj.num2);
}
}
Output is
Constructing singleton instance of A
Setting num2 to 0
1
0

java does not initializes the value of any static or non static data member till it is not called but it creates it.
so So that here when num1 and num2 will be called in main then it will get initialized with values
num1 = 0+1; and
num2=0;

Related

why Java final variables cannot be assigned a value in the setter method?

Non-static final variables can be assigned a value only once.
But why this assignment can happen only either within a declaration or in the constructor?
A final variable is defined to be immutable i.e., the value assigned to it will be the one and only for that variable x. As one can read from the JLS(§4.12.4.)
A variable can be declared final. A final variable may only be
assigned to once.
Now the constructor is just like any other method, except that it is the one that gets executed first when an object (non-static) is created from the class.
Hence, final variables can be assigned through constructors.
For example take the following code:
public class Test {
public final int x;
public Test(int x) {
this.x = x;
}
}
Compiler accepts this invocation because it is guaranteed that for that particular object its class's constructor gets invoked first and doesn't invoked again (i.e. constructor gets invoked one and only one time during the entire lifetime of object.)
However following code throws error: Non-static field 'x' cannot be referenced from a static context
public class Test {
public final int x;
static {
x = 5;
}
public Test(int x) {
this.x = x;
}
}
Since x is not a static field, it cannot be initiated within a static block.
This code would also throw error: Cannot assign a value to final variable 'x'
public class Test {
public final int x;
public Test(int x) {
this.x = x;
}
public void setX(int x) {
this.x = x;
}
}
That is because it is not guaranteed for this object, that the method setX would run first and only once. The programmer could call this method multiple times. Hence, the compiler throws an error.
So there is no way to make a variable "initializable" only once (e.g.,
a setter would block if variable was already assigned before) solely
with java syntax? I thought final might work this way but now I see
it's not.
For your question, you could simply make a variable private and add the condition to the setter method to add value only if variable is null.
For example:
public class Test {
private Integer x;
public Test() {
}
public Test(int x) {
this.x = x;
}
public void setX(int x) {
if (null == this.x) this.x = x;
}
public static void main(String[] args) {
Test y = new Test(5);
System.out.println(y.x);
y.setX(20);
System.out.println(y.x);
}
}
This is not thread safe by the way. I just added a simple example.
What does the keyword final mean in Java?
When used in a class declaration, it means that the class cannot be extended.
When used in a method, it means that the method cannot be overridden.
When used in a method parameter, it means the value of such parameter cannot be changed inside the method. (local constant)
When used in a class field ("variable), it means that it is a global constant.
Values for constants must be resolved at compile time. And, as the word implies, constants fields cannot change value. Therefore, the compiler does not allow the value to be set from a setter (mutator) method.
Contrary to what many believe, for a field to be constant, it does not have to be declared static and final. That said, since the value of a constant cannot be changed, each class instance will share the same value. Therefore, explicitly making them static reenforces this notion.
There is a fifth use of the keyword final and this is when used when local variables are declared. This is a more lengthy explanation.
What happens when you compile code?
I updated my answer because I think part of the problem is that some developers don't quite understand what happens when the code is compiled. As I mentioned before, constant values are resolved at COMPILE TIME. To understand this concept, consider the following example:
public class MyClass {
private final double PI = 3.14159;
// rest of class left out intentionally
}
If I compile this class on my laptop and then I deploy the code to some remote server, how does the server know that the global constant field PI has an assigned value of 3.14159? This is because when I compile this code, this value gets packaged with the byte code. The class constructor doesn't come into play at all in this case. HOWEVER, if the constant field is initialized to its DEFAULT value, then permanent (constant) value may be assigned via the constructor
public class MyClass {
private final double PI; // default value of 0.0
public MyClass(double value) {
PI = value;
}
// rest of code omitted intentionally
}
Here's where declaring a constant as static makes a difference. If a constant is also static, you can't do the above because calling a constructor implies that you can have multiple instances of MyClass and each instance could set a different value. This is clearly a violation of what a static member is. So, if you MUST declare a field as both static and final, understand that you cannot assign a value using this second approach. Only the first one I showed is allowed.
Final Stop's a Variable’s Reassignment
a short simple answer:
Use the keyword final when you want the compiler to prevent a variable from being re-assigned to a different object.
Whether the variable is a static variable, member variable, local variable, or argument/parameter variable, the effect is entirely the same.
Hope this helps friend =)
#StaySafe

Reasons for restrictions on assignment of final variables

Why aren't final variables default initialized? Shouldn't the default constructor initialize them to default values if you are happy with the constant be the default value.
Why must you initialized them in the constructor at all? Why can you can't you just initialize them before using them like other variables?
ex.
public class Untitled {
public final int zero;
public static void main(String[] args)
{
final int a; // this works
a = 4; // this works, but using a field doesn't
new Untitled();
}
}
Untitled.java:2: variable a might not have been initialized
Why must you initialize static final variables when they are declared? Why can't you just initialize them before using them in any other method?
ex.
public class Untitled
{
public final static int zero;
public static void main(String[] args)
{
zero = 0;
}
}
Untitled.java:8: cannot assign a value to final variable zero
I'm asking these question because I'm trying to find a logical/conceptual reason why this won't work, why it isn't allowed. Not just because it isn't.
The idea behind a final variable is that it is set once and only once.
For instance final variables, that means they can only be set during initialization, whether at declaration, in a constructor, or an instance initialization block. For the variable to be set anywhere else, that would have to take place in a non-constructor method, which could be called multiple times - that's why this is off limits.
Similarly for static final variables, they can only be set at declaration or in a static initialization block. Anywhere else would, again, have to be in a method which could be called more that once:
public static void main(String[] args)
{
zero = 0;
main(null);
}
As for your first question, I'm assuming it's an error not to explicitly set a final variable in order to avoid mistakes by the programmer.
The Java Language Specification section 8.3.1.2 spells out the rules for final member variables:
A field can be declared final (§4.12.4). Both class and instance variables (static and non-static fields) may be declared final.
It is a compile-time error if a blank final (§4.12.4) class variable is not definitely assigned (§16.8) by a static initializer (§8.7) of the class in which it is declared.
A blank final instance variable must be definitely assigned (§16.9) at the end of every constructor (§8.8) of the class in which it is declared; otherwise a compile-time error occurs.
The JLS doesn't give reasons why the rules are they way they are. However, it might have come from experience in writing Java code, and the above rules are a way to avoid some common coding errors.
The concept of being final means that the variable value cannot change. If you could do as in your second example, then this variable would have been like any other one (i.e. not final)
I don't ave a good rational regarding your first question.
Because, when looking at your code, the Java compiler has no idea whether a given statement will be executed before an other statement. The only exceptions to this rule are code in constructors and implicit constructors, and that's why they're the only place that final fields can be assigned to.

Initialization of static final fields in Java

public class Main {
static final int alex=getc();
static final int alex1=Integer.parseInt("10");
static final int alex2=getc();
public static int getc(){
return alex1;
}
public static void main(String[] args) {
final Main m = new Main();
System.out.println(alex+" "+alex1 +" "+alex2);
}
}
Can someone tell me why this prints: 0 10 10? I understand that it's a static final variable and its value shouldn't change but it`s a little difficult to understand how the compiler initializes the fields.
It's an ordering problem. Static fields are initialized in the order that they are encountered, so when you call getc() to inititalize the alex variable, alex1 hasn't been set yet. You need to put initialization of alex1 first, then you'll get the expected result.
This situation is covered by JLS 8.3.2.3 "Restrictions on the use of Fields during Initialization".
The JLS rules allows the usage in your Question, and state that the first call to getc() will return default (uninitialized) value of alex.
However, the rules disallow some uses of uninitialized variables; e.g.
int i = j + 1;
int j = i + 1;
is disallowed.
Re some of the other answers. This is not a case where the Java compiler "can't figure it out". The compiler is strictly implementing what the Java Language Specification specifies. (Or to put it another way, a compiler could be written to detect the circularity in your example and call it a compilation error. However, if it did this, it would be rejecting valid Java programs, and therefore wouldn't be a conformant Java compiler.)
In a comment you state this:
... final fields always must be initialized at compile or at runtime before the object creation.
This is not correct.
There are actually two kinds of final fields:
A so-called "constant variable" is indeed evaluated at compile time. (A constant variable is a variable "of primitive type or type String, that is final and initialized with a compile-time constant expression" - see JLS 4.12.4.). Such a field will always have been initialized by the time you access it ... modulo certain complications that are not relevant here.
Other final fields are initialized in the order specified by the JLS, and it is possible to see the field's value before it has been initialized. The restriction on final variables is that they must be initialized once and only once during class initialization (for a static) or during object initialization.
Finally, this stuff is very much "corner case" behavior. A typical well-written class won't need to
access a final field before it has been initialized.
Static final fields whose values are not compile-time constant expressions are initialized in order of declaration. Thus when alex in being initialized, alex1 is not initialized yet, so that getc() returns default values of alex1 (0).
Note that result will be different (10 10 10) in the following case:
static final int alex1 = 10;
In this case alex1 is initialized by a compile-time constant expression, therefore it's initialized from the very beginning.
There is nothing special about static fields, it just that the compiler cannot workout that you are using a method which can access a field before its initialised.
e.g.
public class Main {
private final int a;
public Main() {
System.out.println("Before a=10, a="+getA());
this.a = 10;
System.out.println("After a=10, a="+getA());
}
public int getA() {
return a;
}
public static void main(String... args) {
new Main();
}
}
prints
Before a=10, a=0
After a=10, a=10
Class variables are not necessary to initialize, they are automatically set to their default values. If primitives (like int, short...) it's 0 (zero) for Objects it's null.
Therefore alex1 is set to 0.
Method variables must be initialized, otherwise you will get an compiliation error.
For a better explanation read http://download.oracle.com/javase/tutorial/java/javaOO/classvars.html

Why is there no compilation error on the line above the indicated line?

I'm reading up on Java and I am scratching my head as to why System.out.println("a: " + a); does not yield a compilation error. Where is a ever initialized?
public class localVariableEx {
public static int a;
public static void main(String[] args) {
int b;
System.out.println("a: " + a);
System.out.println("b: " + b); //Compilation error
}
}
The relevant rules of this are described in the JLS § 4.12.5 Initial Values of Variables (emphasis mine):
Each class variable, instance variable, or array component is initialized with a default value when it is created (§15.9, §15.10): [...]
[...]
A local variable (§14.4, §14.14) must be explicitly given a value before it is used, by either initialization (§14.4) or assignment (§15.26), in a way that can be verified by the compiler using the rules for definite assignment (§16).
So while instance variables (such as a) automatically get a default value, local variables (such as b) don't get one and must not be used unless the compiler can verify that a value has been assigned to them.
b is a variable defined in the method scope only, so the compiler can know that no one initialized it before, but a is a public variable that might be initialized somewhere else.
a is of a primitive type int which will get initialized immediately, which means:
Static class members: get init'ed when the class is loaded (most of the time, when the before main(), but it depends on when the class is loaded).
class S {
static int a;
}
Non-Static class members: get init'ed when the object is. (most of the time after new, but there're other, more advanced, methods to new an object).
class S {
int a;
}
Local variables: should be init'ed in the method's scope before first use.
class S {
void foo() {
int b = 0;
}
}
edited after being corrected...

Why to use static in instance variable when we use "this" to call another construtor?

I have little confusion about the below code.
class TestConstructor1{
static int num,num1;
TestConstructor1(int n)
{
this(num,num1);
num=n;
System.out.println("One argument constructor");
System.out.println("Value are "+num+" and "+num1);
}
TestConstructor1(int l,int m)
{
num=l;
num1=m;
System.out.println("Two argument constructor");
System.out.println("Value are "+num+" and "+num1);
}
public static void main(String args[])
{
TestConstructor1 ts=new TestConstructor1(10);
}
};
The constructor is called the way it have to called i.e. it is calling two argument constructor first and then its own constructor but I am interested to know why we have to use static before the instance variable and why we cannot use instance variable without declaring as static.
I am waiting for your responses.Thank You...
You are a little confused about how to chain constructors. Do it like this instead:
private int num,num1; // instance values, initialized by constructors
TestConstructor1(int n)
{
this(n,0);
System.out.println("One argument constructor");
System.out.println("Value are "+num+" and "+num1);
}
TestConstructor1(int n,int m)
{
super(); // this call is implicit and does not explicitly need to be in the code
num=n;
num1=m;
System.out.println("Two argument constructor");
System.out.println("Value are "+num+" and "+num1);
}
Note that the first calls the second passing in the n argument it was given and a suitable default for the second argument.
As to passing instance variables to chained constructors... this is not possible because accessing an instance variable is implicitly a reference to this object, which is not permitted until the call to the super constructor is done, after which you can't invoke another constructor.
But the desire to pass an instance variable to this object's constructor is not logical... in essence you are saying "please initialize this object with itself"... at a point where this object is not yet initialized. It's something of a chicken and egg problem. You can't uses the object's values to initialize those values.
when you say static , it belongs to a class and not a member variable for a specific object .
if you want each instance of TestConstructor1 to have its own copy of the num and num1 then remove static.
In the first line of every Constructor, there is always a call to either super() or this(). Instance variables are set to their defaults, after this call is complete. That's why you cannot use instance variables in calls to super() or this().
You cannot pass instance members in a constructor because the instance is not initialized yet. You can only pass constants like static members which are members of the class:
public static final int DEFAULT_M = 42;
TestConstructor1(int n)
{
this(n, DEFAULT_M);
}
Also you should not call methods except they are static or private and do not access members!
We have to use static because once variables are declared as static they will get memory once only in their life time ,if you don't make them static it will get initialized again and again.

Categories