Initializing static variables in java - java

What exactly is meant by "Static variables are initialized when a class is loaded"? I read lots of discussions available on the net but still I am confused. Step 2 is be the initialization step, right? Then what happens in step 1 "when the class is loaded"?
public class NewClass {
static int[] arr; //Step 1
NewClass(){
arr = new int[10]; //Step 2
for(int i= 0;i<10;i++){
arr[i] = i;
}
}
}

If you want to initialize it when the class is loaded, then you should use the static initializer:
public class NewClass {
static int[] arr; //Step 1
static {
arr = new int[10]; //Step 2
for(int i= 0;i<10;i++){
arr[i] = i;
}
}
}

Initializing a static member in the constructor defeats the purpose of static members, since they don't belong to any instance, and each new instance you'll create will override the value of your static array.
You should either initialize the static variable when it's declared or in a static initialization block.
static int[] arr = new int[10];
or
static {
arr = new int[10];
}
The initialization (i.e. the execution of the static declarations and static initialization blocks) will occur when the class is loaded, which happens when your application first accesses any member (constructor, static method, static variable) of your class.

Step 2 is be the initialization step, right?
No, It's called construction of array. The initialization of array means putting things into it that you are doing after step 2.
Then what happens in step 1 "when the class is loaded"?
when the class is loaded all static variables are initialized with their default values. In case of Object it's default value is null or you can say a reference that is pointing to nothing. No memory is allocated to array at this point of time.
What happens till Step 2 ?
When the object of type NewClass is created using keyword new at that time constructor is called and the array is constructed and memory is assigned for 10 int values in the heap with all zero as default value (till step 2)
What happens after Step 2?
After Step 2 you are actually initializing the array i.e putting the values in it.
static int[] arr; // declaration
arr = new int[10]; // construction
arr[i] = i; // initialization
If you want to read more about it then read book SCJP Sun Certified Programmer for Java 6

When the class is loaded by Class Loader, the job of linker starts. Linker verifies the Java code, whether it is written as per specifications given in Java Language & JVM. If it found valid Java Code then it starts allocating memory for fields, methods, interfaces, etc. Create a reference to that memory locations. Once reference is assigned to memory location, all field variables, methods, interfaces, etc are initialized to there default values, if not specified explicitly. Otherwise, it assigns whatever value is set as its initial value.

Related

Initializing variables in a class

I'm studying computer engineering, my 2nd semester just began. I've been making Android applications for a few while.
My programming lecturer (teaches C++ (Object Oriented)) said we can't initialize variables in a class unless we use a constructor since there's no memory dedicated to those data members before making an object of that class.
He said this is incorrect:
class example
{
int a = 0;
};
But my experience says something else:
I've made a class in my Android project that keeps my Constants. I don't make any objects of that class. I've initialized variables and never used a constructor. But it works fine:
public class Constants {
public static final int a = 1;
}
I want to know how am I initializing variables when there's no memory dedicated to that variable and how it works.
What part of my story is wrong? I want to know how my code works when there's no memory dedicated to my variables (Constants)?
The Truth
class A {
int a = 0;
};
In-class initializers became legal in C++11; so the only conclusion to draw from what you have said is that your teacher is living in the past.
However, if he is teaching C++03 and not a later revision of the language, he's correct about it being ill-formed.
It is important to note that what he said regarding (non-static) data-members and their lack of storage until an object of such class has actually been created still applies.
An in-class initializer will initialize the data-member during construction, as long as the data-member isn't initialized in the used constructor's mem-initializer (then the latter takes precedence).
struct A {
A () = default;
A (int x) : m (x) { }
int m = 0; // ^ mem-initializer
};
A x; // `x.m` is initialized to `0`
A y (123); // `y.m` is initialized to `123`
Further Reading
cppreference.com - Non-static data members : Member Initialization
He said this is incorrect:
class example
{
int a = 0;
}
Well, yes, it's incorrect, there needs to be a semicolon at the end, after the }.
With that semicolon, this is legal C++11; the = 0 is a non-static data member initializer (NSDMI for short). It's syntatic sugar for performing the equivalent initialization in the constructor.
public class Constants {
public static final int a = 1;
}
static things are per-class, and exists even if no objects of that class is ever created. Non-static things are per-object.

How does the static modifier affect this code?

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;

Only array is being modified

This is the code I have, please look at it before you read the question
package ict201jansem2012;
public class Qn3b {
public static void main(String[] args) {
int a = 1;
int b[] = {4,5};
String s = "Good luck!";
method1(b[1]);
System.out.println("(1) b[0] = "+b[0]+"; b[1] = "+b[1]);
method2(b);
System.out.println("(2) b[0] = "+b[0]+"; b[1] = "+b[1]);
method3(a);
System.out.println("(3) a = " + a );
method4(s);
System.out.println("(4) s = " + s );
}
public static void method1(int b) {
b = 7;
}
public static void method2(int[] b) {
b[0] = 3;
}
public static void method3(int a) {
a = 3;
}
public static void method4(String s) {
s = "UniSIM";
}
}
Output:
(1) b[0] = 4; b[1] = 5
(2) b[0] = 3; b[1] = 5
(3) a = 1
(4) s = Good luck!
So my question is ,
This is intresting for me to know as learning programmer. The int b array 0 index value has changed, but not the other variables like the String s and int a. Before i ran this program I roughly thought in my mind that the variable will change their values as the methods are called ,this is because the method is being called and the main method vairable such as a,s and b array are passed and then they are being modified.
So in a nutshell why is that the b array 0 index is changed while the other variables are not changed?
Because you said you were a beginner programmer, I'll do a little writeup to explain (or try to explain) exactly what is happening.
It is because you are passing an argument to your method1 - method4 methods
These arguments, themselves, are references to other objects.
When you use the assignment operator, an equals sign, you overwrite that reference for the value in the current scope - where variables can be 'seen'.
In your code:
In the case of method1 you are creating a new reference, the variable can only be seen within that scope. That is, when you then go b = << expr >> you are assigning the variable b within method1's scope the value, not b in the main scope. The same is true of your method3 and method4 methods, you are assigning a new value to the respective variables within that scope, as you are creating new references rather than altering the original objects.
But, method2's code behaves differently, this is because you are mutating the object inside that code. You are altering the object directly - rather than creating a new reference inside that scope.
Consider the code below
int[] array = new int[] {1, 2};
public void test()
{
method1(array);
System.out.println(array[0] + ", " + array[1]);
method2(array);
System.out.println(array[0] + ", " + array[1]);
}
// because we are working with objects, the identifier, can be different to the arrays identifier
// in this case, I've chosen to use 'a' instead of 'array' to show this
public void method1(int[] a)
{
// this mutates the array object
a[0] = 2;
}
public void method2(int[] array)
{
// this overwrites the method2.array but not the global array
array = new int[] { 1, 2, 3 };
}
We create a new array, with identifer 'array' in the global scope. (In Java, this would be the classes own scope)
In method1, we take an argument, which is the same object being passed as the global array object, so when we mutate it, both objects will change. So, the first print statement will be
"2, 2"
Where array[0] has been altered
N.B. Because we dealing with objects, the 'name' of the variable doesn't matter - it will still be a reference to the same object
However, in method2, we take an argument, like in method1, but this time we use the assignment operator to assign that variable to a new value in the scope that it's currently in - so the global array isn't altered, so we still print out
"2, 2"
For a beginner programmer, I would personally write a few test programs where you get to fully understand how variables and scopes work.
But just know, everytime you create a new block of code, a new scope is created, local variables to that scope can only be seen in that scope and ones below it.
For instance:
public void test()
{
int a = 5;
method1(a);
System.out.println(a); // prints 5
}
public void method1(int a)
{
// a is only viewable in the method1 scope
// and any scopes below it, that is, any scopes created within method1
// and since we use an assignment operator, we assign method1.a a value, not global 'a' a value
a = 123;
if (true)
{
// this is a new scope, variables created in this block cannot be seen outside it
// but can see variables from above it
System.out.println(a); // prints 123
}
}
Here, we create a new scope inside method1 inside the if statement, which can see a above it. However, because method1 and test's scopes are both independent, when we use the assignment operator, we assign the value of a to the local scope. So a is different in both test and method1
I hope you understand better now.
I'm not very good at conveying things, but if it even helped a little bit in understanding scopes I did well, plus, it was fun.
Java is pass-by-value, but most values (everything that's not a primitive, in this case int[] and String) are references, which means they act like pass-by-reference.
Here's a nice writeup: http://javadude.com/articles/passbyvalue.htm
arrays are special type of objects and memory will be allocated on HEAP. When you pass array as parameter to method it will be pass as reference-value (copy of the reference).
This means initial b and this new reference points to same object. Unless new reference points to another object, changes on this reference will reflect on same object. That is why you are seeing value reflected on original array.
All of the values were passed TO the inner methods, but the inner methods returned nothing. However, method2 modified the internal value of the array that was passed to it, so that inner value appeared modified on return.
Note that method2 is the only one where you did not assign to the variable (parameter) itself, but rather assigned to an element of the object whose reference was passed in.
There is a critical difference between modifying the reference (pointer) to an object, and modifying the object itself.

"Final" in java and copying 2D arrays

I am having a little trouble understanding the concept of final in Java.
I have a class that follows:
public class MyClass
{
private int[][] myArray; // intended to be changed
private final int[][] MYARRAY_ORIGINAL; // intended to be unchangable
public MyClass(int[][] array)
{
myArray = array;
MYARRAY_ORIGINAL = array;
}
}
I was under the understanding that final would make MYARRAY_ORIGINAL read only. But I have tried editing myArray, and it edits MYARRAY_ORIGINAL as well. My question is, in this context, what exactly does final do? And for extra credit, how can I copy the array passed through the constructor into MYARRAY_ORIGINAL so that I can have 2 arrays, one to edit, and one that will remain preserved?
Your final MYARRAY_ORIGINAL is indeed read only: you can't assign a new value to the MYARRAY_ORIGINAL reference in other side than class constructor or attribute declaration:
public void someMethod() {
//it won't compile
MYARRAY_ORIGINAL = new int[X][];
}
The values inside the array are not final. Those values can change anytime in the code.
public void anotherMethod() {
MYARRAY_ORIGINAL[0][0] = 25;
//later in the code...
MYARRAY_ORIGINAL[0][0] = 30; //it works!
}
If you indeed need a List of final elements, in other words, a List whose elements can't be modified, you can use Collections.unmodifiableList:
List<Integer> items = Collections.unmodifiableList(Arrays.asList(0,1,2,3));
The last piece of code was taken from here: Immutable array in Java
In case of Objects, final makes reference can't be changed, but object state can be changed.
That is the reason why you are able to change values of final MYARRAY_ORIGINAL
MYARRAY_ORIGINAL is indeed read only variable. Your array reference can not be assigned a new value nor for their length of the arrays can be changed. A final variables initialization can be deferred till the constructors is called. If one tries to modify the reference of the final variable, compiler will throw an error message. But what is possible is, one can edit the elements of the MYARRAY_ORIGINAL and of the myArray i.e one can change the state of the object assigned to a final variable. For example
Class A {
final int[] array;
public A() {
array = new int[10] // deferred initialization of a final variable
array[0] = 10;
}
public void method() {
array[0] = 3; // it is allowed
array = new int[20] // not allowed and compiler will throw an error
}
}
To understand more on final please take a look at Java Language Specification on final variable.
Final does not mean 'read-only' per se, but more so "safe publication' for other threads than the one to which it is defined. Another aim of 'final' is that it ensures the latest object available in a multi-thread environment.
Secondly, if you define something as "final", for example:
private final int[][] MYARRAY_ORIGINAL;
The reference is "final", but not the object itself. A much better way to understand it would be this:
public static final List myList = new ArrayList();
Now I can access myList from any other threads - I can modify it (add to it); but I cannot
(a) Declare it again - myList = new ArrayList();
(b) Assign it another list - myList = anotherList;
The context for final I would see best, in a multiple-thread scenario.
Bonus: to answer your question, you cannot make a 'readonly' array, you will have to manage that yourself (as final, only maintains 'read-only' to reference not object)
You can use the method System.arraycopy to make a copy of the array as follows -
int[][] source = {{1,2},{3,4}};
int[][] copy = new int[source.length][];
System.arraycopy(source, 0, copy, 0, source.length);
Also, you some problem with your code regarding what you are trying to do. If you look at the constructor
public MyClass(int[][] array) { //something else passes the array
myArray = array;
MYARRAY_ORIGINAL = array; // you are just keeping a reference to it can be modified from outside
}
If you really want nobody to modify the values in that array MYARRAY_ORIGINAL, you should make a copy of the source array that comes comes from outside.
public MyClass(int[][] array) {
myArray = array; //make a copy here also if you don't want to edit the argument array
MYARRAY_ORIGINAL = new int[array.length][];
System.arraycopy(array, 0, MYARRAY_ORIGINAL, 0, array.length);
}
Now you shouldn't have to worry about the array's being modified from outside.

Explanation of how classloader loads static variables

Ok so this is a newbie question on java, but i can't seem to get my head around it.
I have the following code inside my class
private static final String [] LIST_CODE = gerarListCode();
private static final int [][] LIST_INTEGER = new int [][] {
{947,947}, {110,103},
{947,958}, {110,120},
{947,954}, {103,107},
{947,967}, {110,99,104}};
private static String [] gerarListCode()
{
String [] listCode = new String [LIST_INTEGER.length];
for (int i=0 ; i<LIST_INTEGER.length ; i++)
{
//do some stuff
}
return listaUnicode;
}
This code is giving me a initialization exception due to a nullpointerexception in the following line
String [] listCode = new String [LIST_INTEGER.length];
Seems the variable LIST_INTEGER is null at that time.
Can someone explain why? is the classloader process linear, in other words, does it invoke the method before fully loading all the other variables?
Yes, in short, it is linear.
"What the compiler actually does is to
internally produce a single class
initialization routine that combines
all the static variable initializers
and all of the static initializer
blocks of code, in the order that they
appear in the class declaration. This
single initialization procedure is run
automatically, one time only, when the
class is first loaded."
Taken from Java in a nutshell.
http://www.developer.com/java/other/article.php/2238491
You should define the variables and then initialize them in a static intitializer block in the correct order, or you could swap the order of the statements as follows:
private static final int [][] LIST_INTEGER = new int [][] { {947,947}, {110,103},
{947,958}, {110,120},
{947,954}, {103,107},
{947,967}, {110,99,104}};
private static final String [] LIST_CODE = gerarListCode();
The JVM will, indeed, initialize the static fields in the order it encounters them.
A class's static fields are initialized when the class is first encountered by the JVM. According to Java Puzzlers, puzzle 49 (which goes on to reference JLS 4.12.5), static fields are first set to their default values. Object variables are set to null, ints are set to 0, etc. After that, their initializers are executed in order of appearance.
So, in your example, LIST_CODE and LIST_INTEGER are first set to null. Then, LIST_CODE is initialized by calling gerarListCode(). LIST_INTEGER is still null when that method is executed. Only after that, LIST_INTEGER is initialized with the literal value you give in your example.

Categories