Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Value of static variable not changed even after initializing the child class in Java [duplicate]

When I invoke the static variable y by using Checks.y (Checks being a subclass), the static block is not executed and the value of y doesn't get updated.

class Par {     static int y = 4; }  class Checks extends Par {     static {         y = 5;     } }  public class Check {     public static void main(String args[]) {         System.out.println(Checks.y); // here printing 4     } } 

As static is shared among all subclasses, the value is supposed to be updated.

What could be the reason behind it?

like image 530
tusharRawat Avatar asked Nov 04 '18 08:11

tusharRawat


People also ask

Can static variables be changed after being initialized?

If you declare a static variable in a class, if you haven't initialized it, just like with instance variables compiler initializes these with default values in the default constructor. Yes, you can also initialize these values using the constructor.

Is it allowed to change the value of static variable in Java?

It is a static variable so you won't need any object of class in order to access it. It's final so the value of this variable can never be changed in the current or in any class.

Can static variable value be changed?

A static variable is common for all instances of the class. A final variable can not change after it has been set the first time. So a static final variable in Java is common for all instances of the class, and it can not be changed after it has been set the first time.

Can we use static variable in child class?

Static methods do not use any instance variables of any object of the class they are defined in.


2 Answers

The field y is not declared by class Checks.

Reading static fields doesn't trigger initialization of the referenced class (Checks), unless that class is the one in which the field is declared (see JLS quote below). In this example, even if y is accessed through Checks, that will only trigger the initialization of Par because Par is the class declaring y.

In other words, the class Checks is in a sense not used at runtime.

This is perhaps one illustration of why it's wrong to access static members through subclasses, something that causes a compile-time warning.


There's a simple explanation in the specification:

12.4.1. When Initialization Occurs

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

  • T is a class and an instance of T is created.

  • A static method declared by T is invoked.

  • A static field declared by T is assigned.

  • A static field declared by T is used and the field is not a constant variable (§4.12.4).

  • T is a top level class (§7.6) and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.
    ...
    A reference to a static field (§8.3.1.1) causes initialization of only the class or interface that actually declares it, even though it might be referred to through the name of a subclass, a subinterface, or a class that implements an interface.

The last note explains why your subclass is not being initialized.

like image 117
ernest_k Avatar answered Oct 05 '22 22:10

ernest_k


From JLS 12.4.1:

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

  • T is a class and an instance of T is created.
  • T is a class and a static method declared by T is invoked.
  • A static field declared by T is assigned.
  • A static field declared by T is used and the field is not a constant variable (§4.12.4).
  • T is a top level class (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.

Since y is not declared in checks, none of the above criteria is satisfied.

Another way to illustrate this behavior:

class par {     static int y = 4;     static {         System.out.println("static constructor of par");     } }  class checks extends par {     static int x = 6;     static {         System.out.println("checks static constructor");         y = 5;     } }  public class check{     public static void main(String args[]){         System.out.println(checks.y);         System.out.println(checks.x);         System.out.println(checks.y);     } } 

Output

static constructor of par 4 checks static constructor 6 5 

So after invoking checks.x that satisfies the second rule, the static constructor gets invoked.

like image 24
Diadistis Avatar answered Oct 05 '22 22:10

Diadistis