A brief introduction to the rewriting of static methods in Java

  • 2020-04-01 01:59:49
  • OfStack

First let's see what the following program will print:


class Dog {
    public static void bark() {
        System.out.print("woof ");
    }
}
class Basenji extends Dog {
    public static void bark() { }
}
public class Bark {
    public static void main(String args[]) {
        Dog woofer = new Dog();
        Dog nipper = new Basenji();
        woofer.bark();
        nipper.bark();
    }
}

At random, it looks as if the program should just print a woof. After all, Basenji extends from Dog, and its bark method definition doesn't do either. The main method calls the bark method, first on a Dog type woofer and second on a Basenji type nipper. The basingi hyena doesn't bark, but apparently this one does. If you run the program, it prints woof woof. What's wrong with the poor little thing?

The problem is that bark is a static method, and calls to static methods do not have any dynamic dispatch mechanism [JLS 15.12.4.4]. When a program calls a static method, the method to be called is selected at compile time based on the compile-time type of the modifier, which is the name of the left part of the dot in the method call expression. In this case, the modifiers for the two method calls are the variables woofer and nipper, both of which are declared as Dog types. Because they have the same compile-time type, the compiler makes them call the same method: dog.bark. This explains why the program prints woof woof. Although nipper's runtime type is Basenji, the compiler only considers its compiler type.

To correct the program, simply remove the static modifier from the two bark method definitions. Thus, the bark method in Basenji will override the bark method in Dog instead of hiding it, and the program will print woof instead of woof woof. By overwriting, you can get dynamic dispatch; By hiding it, you don't get it.


Related articles: