To Discuss more about static variable/block/method.
Can we predict the output of the program?
class Point {
int x, y, useCount;
Point(int x, int y) { this.x = x; this.y = y; }
final static Point origin = new Point(0, 0);
}
class StaticTest {
public static void main(String[] args) {
Point p = new Point(1,1);
Point q = new Point(2,2);
p.x = 3; p.y = 3; p.useCount++; p.origin.useCount++;
System.out.println("(" + q.x + "," + q.y + ")");
System.out.println(q.useCount);
System.out.println(q.origin == Point.origin);
System.out.println(q.origin.useCount);
}
}
It Prints:
(2,2)
0
true
1
If we closely look at JLS it states:
If a field is declared static, there exists exactly one incarnation of the field, no matter how many instances (possibly zero) of the class may eventually be created. A static field, sometimes called a class variable, is incarnated when the class is initialized .
A field that is not declared static (sometimes called a non-static field) is called an instance variable. Whenever a new instance of a class is created, a new variable associated with that instance is created for every instance variable declared in that class or any of its superclasses. The example program:
showing that changing the fields x, y, and useCount of p does not affect the fields of q, because these fields are instance variables in distinct objects. In this example, the class variable origin of the class Point is referenced both using the class name as a qualifier, in Point.origin, and using variables of the class type in field access expressions (§15.11), as in p.origin and q.origin. These two ways of accessing the origin class variable access the same object, evidenced by the fact that the value of the reference equality expression (§15.21.3):
q.origin==Point.origin
is true. Further evidence is that the incrementation:
p.origin.useCount++;
causes the value of q.origin.useCount to be 1; this is so because p.origin and q.origin refer to the same variable.
Now there are couple of rules when overriding a static method.
Can we predict the output of the program?
class SuperClass {
public int k=100;
public static int j=100;
static public String m1() {
return "uk" + j;
}
public String m2() {
return "pp";
}
}
class SubClass extends SuperClass {
public static int k=200;
public int j=20;
public static String m1() {
return "bt";
}
}
public class StaticOverridenExample {
public static void main(String[] args) {
SubClass subClass=new SubClass();
System.out.println(subClass.m1());
System.out.println(subClass.k);
SuperClass sub1=new SubClass();
System.out.println(sub1.m1());
System.out.println(sub1.j);
System.out.println(sub1.k);
}
}
It Prints:
bt
200
uk100
100
100
A compile-time error occurs if an instance method overrides a static method.
A compile-time error occurs if a static method hides an instance method.
Hence try removing static keyword in subclass m() method and vice versa.
In this respect, hiding of methods differs from hiding of fields , for it
is permissible for a static variable to hide an instance variable.
Hence we are able to add static keyword for variable k in subclass
In this respect, overriding of methods differs from hiding of fields ,
for it is permissible for an instance variable to hide a static variable.
Also note A hidden class (static) method can be invoked by using a reference whose type is the class that actually contains the declaration of the method. In this respect, hiding of static methods is different from overriding of instance methods.
Hence we could see output "uk100" when System.out.println(sub1.m1()); is called.
Also never do any manipulation for a static variable in class constructor as values may differ for each object which breaks the rules for static variables.
Now discussing more about Static Blocks Type Parameters one thing to note:
The scope of a class' type parameter is the entire declaration of the class including the type parameter section itself. Therefore, type parameters can appear as parts of their own bounds, or as bounds of other type parameters declared in the same section.
It is a compile-time error to refer to a type parameter of a class C anywhere in the declaration of a static member of C or the declaration of a static member of any type declaration nested within C. It is a compile-time error to refer to a type parameter of a class C within a static initializer of C or any class nested within C.
For Example:
class AStatic
T t;
static {
System.out.println("Came Here" + t);
}
AStatic() {
}
}
public class StaticBlocksTypeParametersDemo {
public static void main(String[] args) {
AStatic
System.out.println(static1.t.parseInt("23232"));
}
}
Gives CompileTime Error as non static field t is been used in static block.
Hope this explanation helps.
3 comments:
It's always useful to keep in mind that static fields exist once per class, BUT a class can be loaded in more than one classloader. And thus, static fields are not per-VM (as you might initially conclude), but per-classloader. Working in an app server or plugin environment using post-delegation classloaders, this comes up a lot.
Alex,
100% agree with you.Thanks a lot for your suggestion.Surely will always rememember your suggestion.
Thanks
Prashant
thnx a lot!!!
good illustrations.
Post a Comment