Sunday 2 April 2017

Static and Final

Static and Final are two famous Java interview topics and you can expect good questions on these two topics. Also from learning perspective these two topics play very important role because of their frequent usage in day to day programming.


1. What is Static?

AnswerStatic is keyword in Java which plays important role in programming because it can be use in different ways as follows:
  • Static member variable: Static member variables doesn't belong to object unlike normal member variables instead they belong to class itself. It means there will be only one copy of static member variable exist in memory which will be shared by all objects. If we update the value of static member variable then same will reflect for all the objects.
  • Static method: Like static member variables static methods too belong to class only and not to the object. We call static methods via class name directly unlike normal member method which we call using object. So to invoke static member methods we don't required object.
  • Static class: We can not have a top level class as static, but we can have inner static class called nested class. We can not have top level class as static because Java creates object for each class of type Class and we know we can't create object of static class.
  • Static block: Static block is an anonymous block which get called automatically whenever Java Class loader loads the class. It can be useful when we want to perform some initialization without creating object. As we know we can do initialization inside constructor as well but for that we need to create object.
We can conclude that static belongs to class and not to object, There is no need of object to call static.

2. How static member(variables or methods) are different from normal members(variable or method)?

AnswerPlease see below code: userCount variable in User class is a static variable. Each time we create an object as you can see we increment userCount by one. We have created four object of User class which means we have incremented value of userCount four times. This is the reason from line 11 to 13 it will print 4 as all four object have same value as 4.
As I mentioned above all object share the same instance of static members.
In this example even if you update the userCount value form user1 object it still will be visible to all other objects of User class.
Please note that for each object of User class if we print the value of userName you will get different value as belong to that object.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class TestStaticMemebr {
 public static void main(String[] args) {
  User user1 = new User("John");
  System.out.println("After fisrt User - User Count = "+ User.userCount);
  User user2 = new User("Sam");
  System.out.println("After second User - User Count = "+ User.userCount);
  User user3 = new User("Andrew");
  User user4 = new User("Tom");
  System.out.println("After third and fourth User - User Count = "+ User.userCount);
  System.out.println("After third and fourth User - user1 = "+ user1.userCount);
  System.out.println("After third and fourth User - user2 = "+ user2.userCount);
  System.out.println("After third and fourth User - user3 = "+ user3.userCount);
  System.out.println("After third and fourth User - user4 = "+ user4.userCount);
 }
}

class User{
 static Integer userCount = 0; //Static variable which hold value of total number of userCreated
 private String userName;//Normal variable
 
 public User(String userName) {
  this.userName = userName;
  userCount = userCount + 1; // Incrementing userCount by 1 for each user.
 }
 
 public String getUserName() {
  return userName;
 }
 public void setUserName(String userName) {
  this.userName = userName;
 }
 
}
So far we are clear that static variables shared by all objects but normal member variables belong to one object.
Normal member variable stored in memory as a part of object but static variable stored with class.

3. How does static block work?

AnswerAs I discussed static block is an anonymous block which get called when Class loader loads your classes.
See whenever you run any Java program very first thing Java does is load all your classes. Class loading happens a way before executing main method.
Since static block get called even before main method executes hence there is no point of existence of any object. It is clear that static block get called directly by Java class loader.
static block is used for initialization purpose without any object. It serves almost same purpose as constructor does but without any object.
Example:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public class TestStaticBlock {

 public static void main(String[] args) {
  Sample sample = new Sample();
  System.out.println("In main method - initialValue:::"+sample.initialValue);
 }
}

class Sample{
 static int initialValue;
 static{
  initialValue = 3;
  System.out.println("In static block - initialValue:::"+initialValue);
 }
}

If you run above code you will get Sysout of line 13 before the Sysout of line 5.
Note: In above example initialValue filed is declared as static, reason behind it as we can not access non static members(variables or methods) from static methods or blocks. 

Follow-up question: Why we can not access non-static members (variables or methods) of a class from a static context (method or block)?

Answer: As we discussed so far static members of a class don't belong to object and they can exist without any object. But non static members of a class can't exist without object.
So if you try to call not static members of a class from static context(method or block) you do need an object .
So in order to call non static members from static context(method or block) we need object.
Note: Vice versa of it doesn't hold true i.e we can access static members of a class from non static context(method or block) of a class, because static members don't belong to any object.
Example: 1.There is no compilation error at line 4 and 15, as at both places we making call to non static method from a static method.
2.There is compilation error at line 9 since we are trying to access non static method from static method, but at line 10 there is no error once we have object.
3.There is no compilation error at line 5 and 14 as we are making method function call from non static method.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class Sample{
 
 void show(){
  get(); //No compilation error
  update(new Sample());
 }
 
 static void update(Sample s){
  show() // Compilation error
  s.show(); //No compilation error
 }
 
 void get(){
  update(new Sample());//No compilation error
  show(); //No compilation error
 }
}



4. Static and override:  Can we override static methods?

Answer:  No, We can't override static methods. As we know overriding is form of dynamic or run time polymorphism in which method invocation resolves at run time depends on type of object passed i.e if we pass object of parent class then method of parent class will get called and if we pass object of child class object then child's version of method will get called.
As we know static methods don't belong to object and there will be only one copy of static exist in memory for all the object. So it doesn't matter which object(parent or child) you are passing, at the end same method will get invoked.
From above two fact it is clear we can't override static method, but if we trying to do so then compiler won't complain because that is not method overriding instead it will be Method Hiding.
Whenever we try to override static method of parent class in child we actually hide the parents version of method in child class by providing a new implementation and we call it Method Hiding
Example:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class TestStaticOverriding {
 public static void main(String[] args) {
  Account.deposit(100);
  Account.withdraw(100);
  
  SavingAccount.deposit(200);
  SavingAccount.withdraw(200);
 }
 
}

class Account{
 static void deposit(int amount){
  System.out.println("Account's deposit called");
 }
 
 static void withdraw(int amount){
  System.out.println("Account's withdraw called");
 }
}

class SavingAccount extends Account{
 //@Override // If we uncomment @Override annotation compiler will give error because it is not overriding.
 static void deposit(int amount){
  System.out.println("Saving Account's deposit called");
 }
}


Lets's discus Final now :

1.What is Final?

AnswerFinal is a keyword in Java which plays very important role same as static, We can use final keyword in following ways:
  • Final variables: We can declare any class level variables or local variables as final, Whenever we make any variable final it means once you have initialized the value of it you can not modify it through out the program. As name final suggests you actually finalize the value of you variable at declaration time and has to use same all the way in you program. If you try to modify value of final variables after initialization compiler will throw error.
  • Final methods: We can make methods of a class final and making a method final means we can not override that method in child classes. So you can not override a final method in child class.
  • Final class: We can mark classes final as well, Whenever we make a class final we imposing a restriction that is no other can extend it. So when you make your class final It means no other classes are allowed to extend it.
Note: Whenever we try to modify value of final variables or try to override final methods or try to extend final class we will get compile time exception in all three cases.

2. How final works for primitive type and for non primitive types? 

Example: See in below example we have two final variables first employeeId which is primitive type and second department which is custom type(non primitive).

Let's first look on employeeId(primitive type) we declared it at line number 2 and we are doing initialization at line number 8 and we are trying to modify value of it at line number 12 but we are getting compilation error at line 12 since it is not allowed to modify value of final variables.

Now one more point I want to highlight that you are only allowed to do initialization of final variables either at declaration(line 2 in our case) or inside constructor(line 8 in our case).

Let's take a look on department(non-primitive type) we declared it at line number 4 and we are doing initialization at line number 7. We are trying to modify value of deptName variable at line 13 but we are not getting any compilation error at line 13 because we are not modifying the department variable(which is final) instead we are modifying deptName which is property of department object.


So Please note that what we are trying to do at line 14 is not allowed because here as we are breaking rule of final by assigning a new object to department variable since we have already assigned once. This is the reason we are getting compilation error. So line number 13 is absolutely fine but line number 14 is against the rules of final.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22

class Employee{
 final int employeeId;
 
 final Department department;
 
 public Employee(){
  department = new Department("HR"); 
  employeeId = 1234;
 }
 
 public void updateInfo(){
  employeeId = 3456;
  department.deptName = "ADMIN";
  department = new Department("ADMIN"); 
 }
}

class Department{
 String deptName;
 public Department(String deptName){
  this.deptName = deptName;
 }
}



No comments:

Post a Comment