簡體   English   中英

從靜態方法調用超級方法

[英]calling a super method from a static method

是否可以從子靜態方法調用超靜態方法?

我的意思是,以通用的方式,到目前為止,我有以下內容:

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

在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 ,運行時系統調用在調用方法的引用的編譯時類型中定義的方法。

換句話說,對靜態方法的調用是在編譯時映射的,並且取決於引用的聲明類型(在本例中為Parent),而不是運行時引用指向的實例。 在該示例中, myAnimal的編譯時類型是Animal 因此,運行時系統調用Animal定義的hide方法。

一個在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類似的關鍵字 - 但是(壞)理由可能是“超類的名稱是在這個類的聲明中寫的,所以你不得不重新編譯你的類來改變它,所以你也可以在這里改變靜態調用。“

整個繼承概念不適用於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 即,被調用的方法取決於如何聲明變量而不是其他。

實際上,您可以以通用方式調用超類的靜態方法,前提是您知道方法名稱及其參數。

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";
    }
}

這應該可以工作,並且在子類中,您可以在基類中設置所有內容。

輸出應該是:

來自Base的你好

myVar =好

您的實現的官方名稱稱為方法隱藏 我建議引入一個靜態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)。

對於靜態方法,不需要類的實例,因此沒有超級。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM