Вызов супер-метода из статического метода

Можно ли вызвать суперстатический метод из дочернего статического метода?

Я имею в виду, что в общем случае до сих пор у меня есть следующее:

public class BaseController extends Controller {
    static void init() {
        //init stuff
    }
}

public class ChildController extends BaseController {
    static void init() {
        BaseController.loadState();
        // more init stuff
    }

}

и он работает, но я хотел бы сделать это в общем виде, что-то вроде вызова super.loadState(), который, похоже, не работает...

Ответ 1

В Java статические методы нельзя переопределить. Причина детально объясняется здесь

Таким образом, он не зависит от объекта, на который он ссылается. Но вместо этого это зависит от типа ссылки. Следовательно, статический метод, как говорят, скрывает другой статический метод и не отменяет его.

Например (Cat является подклассом Animal):

public class Animal {
    public static void hide() {
        System.out.format("The hide method in Animal.%n");
    }
    public void override() {
        System.out.format("The override method in Animal.%n");
    }
}

public class Cat extends Animal {
    public static void hide() {
        System.out.format("The hide method in Cat.%n");
    }
    public void override() {
        System.out.format("The override method in Cat.%n");
    }
}

Основной класс:

public static void main(String[] args) {
    Cat myCat = new Cat();
    System.out.println("Create a Cat instance ...");
    myCat.hide(); 
    Cat.hide();
    myCat.override();  

    Animal myAnimal = myCat;
    System.out.println("\nCast the Cat instance to Animal...");
    Animal.hide();     
    myAnimal.override();

    Animal myAnimal1 = new Animal();
    System.out.println("\nCreate an Animal instance....");
    Animal.hide();     
    myAnimal.override();
}

Теперь результат будет таким, как указано ниже

Create a Cat instance ...
The hide method in Cat.
The hide method in Cat.
The override method in Cat.  

Cast the Cat instance to Animal...
The hide method in Animal.
The override method in Cat.

Create an Animal instance....
The hide method in Animal.
The override method in Animal.

Для class methods система выполнения вызывает метод, определенный в типе времени компиляции ссылки, на которую вызывается метод.

Другими словами, вызов статических методов отображается во время компиляции и зависит от объявленного типа ссылки (в данном случае это Родитель), а не экземпляр опорных точек во время выполнения. В этом примере тип времени компиляции myAnimal равен Animal. Таким образом, система времени выполнения вызывает метод hide, определенный в Animal.

Ответ 2

Там есть статическое наследование в Java. Адаптация примера от Никиты:

class A {
    static void test() {
        System.out.print("A");
    }
}
class B extends A {
}

class C extends B {
    static void test() {
        System.out.print("C");
        B.test();
    }

    public static void main(String[] ignored) {
       C.test();
    }
}

Теперь это компилируется и, конечно, вызывается C-печатьми "CA". Теперь мы изменим класс B на это:

class B extends A {
    static void test() {
        System.out.print("B");
    }
}

и перекомпилировать только B (не C). Теперь вызывая C снова, он будет печатать "CB".

Нет ключевого слова super как для статических методов, хотя - (неправильное) оправдание может быть так: "Имя суперкласса написано в объявлении этого класса, поэтому вам пришлось перекомпилировать ваш класс тем не менее для меняя его, чтобы вы могли также изменить статические вызовы здесь."

Ответ 3

Вся концепция наследования не применяется к статическим элементам в Java. Например, статический метод не может переопределить другой статический метод.
Таким образом, нет, вам придется называть его по имени или создавать им методы экземпляра какого-либо объекта. (Возможно, вы захотите проверить один из шаблонов factory в частности).

Практический пример

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

    A a = new B();
    B b = new B();
    a.test();
    b.test();

Отпечатает A, а затем B. I.e., метод invoked зависит от того, как объявлена ​​переменная и ничего больше.

Ответ 4

Официальное название вашей реализации называется метод скрытия. Я бы предложил ввести статический метод init (Controller controller) и вызвать метод экземпляра, чтобы воспользоваться преимуществом переопределения.

public class Controller {
   static void init(Controller controller) {
      controller.init();
   }

   void init() {
      //init stuff
   }
}

public class BaseController extends Controller {

   @override
   void init() {
      super.init();
      //base controller init stuff
   }

}

public class ChildController extends BaseController {
   @override
   void init() {
      super.init();
      //child controller init stuff
   }
}

Затем вы можете вызвать Controller.init(controllerInstance).

Ответ 5

Фактически вы можете вызвать статический метод суперкласса, учитывая, что вы знаете имя метода и его параметры.

public class StaticTest {

    public static void main(String[] args) {
        NewClass.helloWorld();
    }    
}

public class NewClass extends BaseClass {
    public static void helloWorld() {
        try {
            NewClass.class.getSuperclass().getMethod("helloWorld", new Class[] {}).invoke( NewClass.class ,new Object[]{} );
        } catch (Exception e) {
            e.printStackTrace();
        } 

        System.out.println("myVar = " + myVar);
    }
}

public class BaseClass extends BaseBaseClass {
    protected static String myVar;
    public static void helloWorld() {
        System.out.println("Hello from Base");
        myVar = "Good";
    }
}

Это должно работать, и в подклассе у вас есть все, что установлено в базовом классе.

Выход должен быть:

Привет из базы

myVar = Хорошо

Ответ 6

Для статических методов нет экземпляра требуемого класса, поэтому супер не существует.