简体   繁体   中英

If static methods can't be overridden, how its working here (For Java)?

My understanding was that static variables and static methods are of a class, not of the class objects. So an Override of a static method won't work in Java, as for overriding we need an instance of a class to be created. But I was trying something today that contradicted my knowledge of Java.

Please follow this code:

class Parent{
   public static void doIt(){
      System.out.println("In static method 'doit' of class Parent ");
   }
}

class Child extends Parent{    
   public static void doIt(){
      System.out.println("In static method 'doit' of class Child ");
   }
}

public class StaticPractise{
   public static void main(String[] args){
      Parent.doIt();
      Child.doIt();
   }    
}

The output of the above implementation is:

D:\Rahul Shivsharan\MyPractise\JAVA>java StaticPractise
In static method 'doit' of class Parent
In static method 'doit' of class Child

From this output I can understand that though the Child class extends the Parent class, the doit methods are individual to each class as they are static . So no overriding of them is allowed.

Now please follow the below code, where @Override is added to the child's doIt method:

class Parent{
   public static void doIt(){
      System.out.println("In static method 'doit' of class Parent ");
   }
}

class Child extends Parent{    
   @Override // Adding this annotation here
   public static void doIt(){
      System.out.println("In static method 'doit' of class Child ");
   }
}

public class StaticPractise{
   public static void main(String[] args){
      Parent.doIt();
      Child.doIt();
   }    
}

The output of the above code gives a compilation error as follows:

D:\Rahul Shivsharan\MyPractise\JAVA>javac StaticPractise.java
StaticPractise.java:31: error: method does not override or implement a method from a supertype
    @Override
    ^
1 error

Here it clearly says that the annotation Override can't be applied in static methods as they are not getting overridden.

Now please follow the below code, where Child has no doIt method:

class Parent{
   public static void doIt(){
      System.out.println("In static method 'doit' of class Parent ");
   }
}

class Child extends Parent{ /* no doIt method */ }

public class StaticPractise{
   public static void main(String[] args){
      Parent.doIt();
      Child.doIt();
   }    
}

The output is:

D:\Rahul Shivsharan\MyPractise\JAVA>java StaticPractise
In static method 'doit' of class Parent
In static method 'doit' of class Parent

Why does the above code compile and run? I was expecting a compilation error for method doit for class Child, and I was expecting "Method not found". I don't understand.

Also please follow the below code. Here, the doIt method in Parent is now final .

class Parent{
   public static final void doIt(){ // now final
      System.out.println("In static method 'doit' of class Parent ");
   }
}

class Child extends Parent{
   public static void doIt(){
      System.out.println("In static method 'doit' of class Parent ");
   }
}

public class StaticPractise{
   public static void main(String[] args){
      Parent.doIt();
      Child.doIt();
   }    
}

The output after running the above code is as follows:

D:\Rahul Shivsharan\MyPractise\JAVA>javac StaticPractise.java
StaticPractise.java:30: error: doIt() in Child cannot override doIt() in Parent
    public static void doIt(){
                       ^
  overridden method is static,final
 1 error

 D:\Rahul Shivsharan\MyPractise\JAVA>

What I was expecting was that the above code should work fine as the doit methods are static in each class, so even a final keyword should not make any compilation error as the method is static .

Please explain to me how method overriding works in static classes in Java.

  1. Can static methods be overridden? If yes, then how come annotating @Override fails?
  2. If static methods can't be overridden, then how come my 3rd code block runs fine?
  3. If static methods can't be overridden, then how come the final keyword makes a difference?

First of all there are different mechanisms involved here: Overriding and Shadowing (also called hiding) .

1) Static methods cannot be overriden as they are attached to the class they are defined in. However, you can shadow/hide a static method as you are doing with your Parent / Child class. This means, the method gets replaced in the Child class but is still available from the Parent class.

It gets more obvious that you are not overriding when you are calling the static methods from instances of those classes (and not using the Class.staticMethod() invocation).

Parent parent = new Parent();
Child child1 = new Child();
Parent child2 = new Child();

parent.StaticMethod();
child1.StaticMethod();
child2.StaticMethod();

the output is

Static method from Parent
Static method from Child
Static method from Parent

The answer is the dispatch of the methods. You can grab the source code here

2) The dispatch finds the method on the Parent class. There is no dynamic dispatch as that the runtime type is used to find the method handle. It uses the compile time type. Remind : Calling static methods from instances is considered bad practice since things like above can happen and are easy to be overlooked.

3) With final you declare that the method cannot be overridden neither shadowed/hidden.

你混淆了压倒一切的隐藏

Although it is discouraged to ask 3 questions in one post, I am still willing to answer them.

  1. Static methods cannot be overridden because there is no point of doing that. In your case, If you want to override the static method you can just call the method and add your own implementation after that or you just create another method.

  2. So now that you know that static methods cannot be overridden. But you are asking why the third code works? The third code is the code with

    public class Child extends Parent {}

right? Although static methods cannot be overridden, they can be inherited . What you are doing is inheriting Parent so that is completely fine!

  1. Now let me tell you, in your first code sample you are hiding the method in the Parent class, not overriding. That's why you get the output. A final keyword means the method can never be changed, not even hidden. So that's why.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM