Saturday, June 12, 2021

Java Tutorial: The static Keyword

Chapters

The static Keyword

Classes, variables, methods and blocks with static keyword belong to the class itself. It means, static members don't need an instance of a class in order to be accessed.

Static members are always initialized first before class instance initialization because, when a class is loaded into the JVM, static members are also initialized. Classes need to be loaded first into the JVM before our program can instantiate them.
Note: static keyword is not allowed in top-level classes.
public class SampleClass{
  //static variable
  static String name = "SampleClass";
  //non-static variable
  int num = 1;
  
  //static method
  static int add(int n1,int n2){
    return n1 + n2;
  }
  
  //non-static method
  int multiply(int n1,int n2){
    return n1 * n2;
  }
  
  //non-static method
  void displayName(){
    System.out.println("Display name in displayName(): ");
    //static members can be accessed in non-static
    //context
    System.out.println(name);
  }
  
  public static void main(String[]args){
  
    //error: non-static members can't directly
    //be accessed in static context
    //System.out.println(num);
    //System.out.println(multiply(2,2));
    
    //static members can be directly accessed
    //in static context
    System.out.println(name);
    System.out.println(add(2,2));
    
    //non-static members can be indirectly
    //accessed in static context by instantiation
    SampleClass sc = new SampleClass();
    System.out.println(sc.num);
    System.out.println(sc.multiply(2,2));
    sc.displayName();
    System.out.println();
    
    //class instance can access static members
    //and static members are shared across
    //the class instances.
    System.out.println("Accessing static members through"+
                       " class instances.");
    System.out.println(sc.name);
    SampleClass sc2 = new SampleClass();
    System.out.println(sc2.name);
    System.out.println();
    
    ClassA classA = new ClassA();
  }
}

class ClassA{
  
  ClassA(){
    System.out.println("ClassA constructor");
    
    //when accessing a static member of a class
    //to another class, write the class name first
    //then dot(.) then the variable name
    System.out.println("Call SampleClass.name in ClassA:" +
                       SampleClass.name);
                       
    //All instances of SampleClas share the same
    //static members.
    //Take a look at this example
    SampleClass sc1 = new SampleClass();
    SampleClass sc2 = new SampleClass();
    sc1.name = "Modified";
    System.out.println("Call SampleClass.name in sc2:" +
                       sc2.name);
    
  }
}
Note: We can think of "static context" as context that is related to static elements like static methods, fields, etc.
Alright! There are lots of interesting things happening in the example above. We can see above that a static member can be directly access in a non-static class member. You might ask: "why?". I already explained the answer in the introduction of this chapter, though, I'm gonna explain it again here.

Static members are initialized during class loading into the JVM. Classes need to be loaded first into the JVM before our program can create instances of them. If we insist on putting non-static member in a static context then we will encounter nasty exceptions like NullPointerException,NoClassDefFoundError,etc. That's why java prohibits non-static members in a static context.

However, we can indirectly access non-static members in a static context by instantiating the class first. If successful, Java knows that the class is loaded and its instance is successfully created. Thus, Java knows its non-static members exist.

When we wanna call a static member of a class to another class then, we need to write the class name first then dot(.) then the variable name like this code in the example above: SampleClass.name

As long as static members are not private, they will be shared with every instance of the class and with the class subclasses. That's why a class instance can call static class members.

Static Class Members In Inheritance

Static variables, methods and classes are inherited by sub class during inheritance. However, static methods can't be overriden.
public class SampleClass{
  
  public static void main(String[]args){
   
     ClassB b = new ClassB();
     b.displayName();
     b.displayParentName();
  }
}

class ClassA{
    protected static String name;
	
    static void displayName(){
      System.out.println(name);
    }
}

class ClassB extends ClassA{
	static String name;
	
	//error: @Override annotation
	//can't be placed because static
	//methods can't be overriden
	//@Override
	static void displayName(){
		//error: can't put super()
		//in static context because
		//call to super is non-static
		//super.displayName();
		System.out.println(name);
	}
	
	void displayParentName(){
		//can call parent class
		//displayName()
		super.displayName();
	}
	
	ClassB(){
		//can call parent class
		//name variable
		super.name = "ClassA";
		name = "ClassB";
	}
}
As you can see from the example above, we can't use @Override annotation in the displayName() of ClassB because displayName() in ClassB doesn't override displayName() in ClassA. Though, we can still call displayName() of ClassA from ClassB because it's just hidden.

No comments:

Post a Comment