Overriding a static method in Java


You can't override static methods in Java. But why does the following code work:

public class Runner {
    public static void main(String[] args) {
        B.fun();
    }
}

class A {
    public static void fun() {
        System.out.println("A");
    }
}
class B extends A {
    public static void fun() {
        System.out.println("B");
    }
}

"B"is printed. It looks like it's an override. Because when overloading, I would have to change something in the method signature. But no, I didn't change anything.

I can't put the "override" annotation above the method.

Author: Верхова Галина, 2020-05-20

2 answers

Let's start in order

Redefining a method:

Redefining a method (Method overriding) is a language feature that allows a subclass or child of a class to provide a specific implementation of a method that has already been implemented in one of the superclasses or the parent class. The redefinition looks like this:

public class App {
    public static void main(String[] args) {
        Dog dog = new Dog();
        Cat cat = new Cat();
        
        dog.voice(); // Вывод: Гав
        cat.voice(); // Вывод: Мяу
    }
}

class Animal { // родительский класс
    public void voice() {
        System.out.print("Голос животного");
    }
}

class Dog extends Animal { // класс-наследник

    @Override // Переопределение метода voice() унаследованного от класса Animal в классе-наследнике Dog
    public void voice() {
        System.out.print("Гав");
    }
}

class Cat extends Animal { // класс-наследник

    @Override // Переопределение метода voice() унаследованного от класса Animal в классе-наследнике Cat
    public void voice() {
        System.out.print("Мяу");
    }

}

The overridden method must have the same access modifier as its parent, accept arguments as its parent. the parent, and have the return type the same as its parent
I.e.

public class App {
    public static void main(String[] args) {
        Dog dog = new Dog();
        Cat cat = new Cat();
        
        dog.voice("Шарик", 10); // Вывод: Гав
        cat.voice("не Шарик", 7); // Вывод: Мяу
    }
}

class Animal {
    // Родительский метод имеет возвращаемый тип String. Принимает два параметра, типа String и int
    public String voice(String animal_name, int animal_age) {
        System.out.print("Гав");
        
        return animal_name;
    }
}

class Dog extends Animal{
    // Переопределенный метод должен как его родитель, иметь возвращаемый тип String, и принимать параметры как его родитель 
    @Override
    public String voice(String dog_name, int dog_age) {
        System.out.print("Гав");
        
        return dog_name;
    }
}

class Cat extends Animal {
    @Override
    public String voice(String cat_name, int cat_age) {
        System.out.print("Мяу");        
        return cat_name;
    }
}

Hiding the method:

Hiding methods, roughly speaking, is an "overlap" of the method of the current class, the method of the parent class. It looks like this:

public class App {
    public static void main(String[] args) {
        Dog.voice(); // Вывод: Гав
    }
}

class Animal {
    public static void voice() {
        System.out.print("звук");
    }
}
class Dog extends Animal {
    // Метод определенный в классе-наследнике идентичный по сигнатуре с методом родительского класса
    public static void voice() {
        System.out.print("Гав");
    }
}

The method signatures of these two classes are identical, i.e. the parent class Animal has public static void voice() and the descendant class Dog has public static void voice(). Therefore, calling Dog.voice() will call the method defined in the class Dog

It is important to note that overlapping requires the same rules as overriding a method.

The overridden method must have the same access modifier as its parent, accept arguments as its parent, and have the return type the same as its parent

I.e.

public class App {
    public static void main(String[] args) {
        Dog.voice(); // Вывод: Гав
        Dog.voice("Шарик"); // Вывод: Шарик говорит гав
    }
}

class Animal {
    public static void voice() {
        System.out.print("звук");
    }
}

class Dog extends Animal {
    
    public static void voice() { // Метод перекрывающий унаследованный метод
        System.out.print("Гав");
    }
    
    public static void voice(String name) { // Отдельный метод класса Dog
        System.out.print(name + " говорит гав");
    }
    
}

Consider the use of such methods in your classes

  1. Using a method without a similar signature
public class App {
    public static void main(String[] args) {
        Dog.voice(); // Вывод: звук
    }
}

class Animal {
    public static void voice() {
        System.out.print("звук");
    }
}

class Dog extends Animal {  
    public static void dog_voice() {
        voice();
    }
}

Since in if there is no method implemented in the descendant class that is similar in signature to the parent class, then the method inherited from the parent class is used

  1. Using a similar signature method
public class App {
    public static void main(String[] args) {
        Dog.dog_voice(); // Вывод: гав
    }
}

class Animal {
    public static void voice() {
        System.out.print("звук");
    }
}

class Dog extends Animal {
    
    public static void voice() {
        System.out.print("Гав");
    }
    public static void dog_voice() {
        voice();
    }
}

Since the Dog class now has "its own method" voice(), it overrides the method inherited from Animal

  1. Using a method inherited from a parent when there is a method overriding it
public class App {
    public static void main(String[] args) {
        Dog.dog_voice(); // Вывод: Гавзвук
    }
}

class Animal {
    public static void voice() {
        System.out.print("звук");
    }
}

class Dog extends Animal {
    
    public static void voice() { // Метод перекрывающий унаследованный метод
        System.out.print("Гав");
    }
    
    public static void dog_voice() {
        voice(); // Вызов метода voice определенного в классе Dog;
        Animal.voice(); // Вызов метода voice определенного в классе Animal 
    }
}

I want to add the following topics, that the overlap works not only with the methods of the class, but also with its fields. A small example:

public class App {
    public static void main(String[] args) {
        Dog.animal(); // Вывод: Имя этого животного Собакен
    }
}
class Animal {
    public static String animal_name = "Нет имени, просто животное";
    
    public static void animal() {
        System.out.print("Имя этого животного " + animal_name);
    }
}
class Dog extends Animal {
    public static String animal_name = "Собакен"; // Перекрывает поле родительского класса Animal
    
    public static void animal() {
        System.out.print("Имя этого животного " + animal_name);
    }
}
 3
Author: midnightelf18, 2020-06-12 12:52:24

There are cases when we REDEFINE the method, and there are cases when we HIDE the method. In your case, there is a "hiding", not a "redefinition" of the method.

Static methods DO NOT" override " superclass methods. Static methods are able to "hide" a method from a superclass. At first glance, it may SEEM that "redefining" and "hiding" are the same thing. Here is written what is the difference between them.

 1
Author: Marika, 2020-05-25 13:36:18