24

是否可以从子静态方法调用超静态方法?

我的意思是,以一般的方式,到目前为止,我有以下内容:

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(),这似乎不起作用......

4

6 回答 6

17

在 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,运行时系统调用在调用该方法的引用的编译时类型中定义的方法。

换句话说,对静态方法的调用是在编译时映射的,并且取决于引用的声明类型(在本例中为父级),而不是运行时引用点的实例。在示例中,编译时类型myAnimalAnimal. 因此,运行时系统调用定义在Animal.

于 2011-02-20T19:45:26.667 回答
7

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”。

但是,静态方法没有superlike 关键字 - 一个(不好的)理由可能是“超类的名称写在这个类的声明中,所以你必须重新编译你的类来改变它,所以你可以也改变这里的静态调用。”

于 2011-02-20T19:08:55.917 回答
4

整个继承概念不适用于 Java 中的静态元素。例如,静态方法不能覆盖另一个静态方法。
因此,不,您必须按名称调用它或使它们成为某个对象的实例方法。(您可能特别想检查一种工厂模式)。

一个实际的例子

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。即,调用的方法取决于变量的声明方式,仅此而已。

于 2011-02-20T18:33:29.630 回答
2

假设您知道方法名称及其参数,您实际上可以以通用方式调用超类的静态方法。

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 = 好

于 2016-08-21T07:04:42.230 回答
1

您的实现的正式名称称为方法隐藏。我建议引入一个静态 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)。

于 2011-02-20T19:17:30.407 回答
0

对于静态方法,不需要类的实例,因此没有超级。

于 2011-02-20T18:43:49.893 回答