140

私は静的メソッドでモディファイアをいじっていて、奇妙な振る舞いに出くわしました。

ご存知のように、静的メソッドはインスタンスではなくクラスに関連付けられているため、オーバーライドできません。

したがって、以下のスニペットがある場合は、正常にコンパイルされます

//Snippet 1 - Compiles fine
public class A {
    static void ts() {
    }
}

class B extends A {
    static void ts() {
    }
}

しかし、クラスAの静的メソッドにfinal修飾子を含めると、コンパイルが失敗し ます。Bのts()はAのts()をオーバーライドできません。オーバーライドされたメソッドは静的finalです。

静的メソッドをまったくオーバーライドできないのに、なぜこれが発生するのですか?

4

8 に答える 8

179

静的メソッドはオーバーライドできませんが、非表示にすることはできます。Bのts()メソッドはAのメソッドをオーバーライドしません(ポリモーフィズムの影響を受けません)ts()が、それを非表示にします。ts()B(NOTA.ts()またはB.ts()... just )を呼び出すと、Ats()ではなくBの1つが呼び出されます。これはポリモーフィズムの影響を受けないためts()、Aの呼び出しがBの呼び出しにリダイレクトされることはありません。

キーワードfinalは、メソッドが非表示になるのを無効にします。したがって、非表示にすることはできず、非表示にしようとするとコンパイラエラーが発生します。

お役に立てれば。

于 2009-11-16T17:47:38.133 に答える
15

静的メソッドはオーバーライドできません

これは正確には真実ではありません。サンプルコードは、実際には、BのメソッドtsがAのメソッドtsを非表示にすることを意味します。したがって、正確にオーバーライドされるわけではありません。Javaranchについては、すばらしい説明があります。

于 2009-11-16T17:48:02.373 に答える
11

静的メソッドは、インスタンスではなくクラスに属します。

A.ts()B.ts()常に別々のメソッドになります。

本当の問題は、Javaではインスタンスオブジェクトの静的メソッドを呼び出せることです。親クラスからの同じシグニチャを持つ静的メソッドは、サブクラスのインスタンスから呼び出されたときに非表示になります。ただし、 finalメソッドをオーバーライド/非表示にすることはできません。

エラーメッセージは、オーバーライドされるのではなく、hiddenという単語を使用すると思います...

于 2009-11-16T17:55:26.760 に答える
8

次のことを考慮して、静的メソッドを最終的なものにすることを検討する立場にいることに気付くかもしれません。

次のクラスがあります。

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

これらのメソッドを呼び出す「正しい」方法は次のようになります。

A.ts();
B.ts();

その結果、ABインスタンスのメソッドを呼び出すこともできます。

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

その結果ABも同様になります。

ここで、次のことを考慮してください。

A a = new B();
a.ts();

それは印刷されますA。あなたは実際にクラスのオブジェクトを持っているので、それはあなたを驚かせるかもしれませんB。ただし、タイプの参照から呼び出しているため、Aを呼び出しますA.ts()B次のコードで印刷できます。

A a = new B();
((B)a).ts();

どちらの場合も、あなたが持っているオブジェクトは実際にはクラスからのものですB。ただし、オブジェクトを指すポインタに応じて、からAまたはからメソッドを呼び出しますB

ここで、あなたがクラスの開発者でありA、サブクラス化を許可したいとします。しかし、サブクラスから呼び出された場合でも、メソッドが本当に必要ですts()。これは、サブクラスのバージョンによって隠されないように、メソッドが実行したいことを実行します。final次に、それを作成して、サブクラスに隠されないようにすることができます。そして、次のコードがクラスからメソッドを呼び出すことを確認できますA

B b = new B();
b.ts();

確かに、それはどういうわけか構築されていますが、場合によっては意味があるかもしれません。

インスタンスで静的メソッドを呼び出すのではなく、クラスで直接呼び出す必要があります。そうすれば、その問題は発生しません。また、たとえばIntelliJ IDEAは、インスタンスで静的メソッドを呼び出した場合、および静的メソッドをfinalにした場合にも、警告を表示します。

于 2017-09-12T11:53:51.297 に答える
0

Bのts()メソッドはAのts()メソッドをオーバーライドするのではなく、単に別のメソッドです。Bクラスは静的であるためAのts()メソッドを認識しません。したがって、ts()と呼ばれる独自のメソッドを宣言できます。

ただし、メソッドがfinalの場合、コンパイラーは、Bでオーバーライドしてはならないts()メソッドがAにあることを認識します。

于 2009-11-16T17:49:20.640 に答える
0

ここでは、コンパイルエラーはかなり誤解を招くものだったと思います。「オーバーライドされたメソッドは静的finalです」と言うべきではありませんでしたが、代わりに「オーバーライドされたメソッドはfinalです」と言うべきでした。ここでは、静的修飾子は関係ありません。

于 2009-11-16T18:10:54.047 に答える
0

非静的メソッドとは異なり、静的メソッドはJavaでオーバーライドできません。ただし、静的および非静的データメンバーのように継承されます。そのため、同じ名前の非静的メソッドを親クラスに作成することはできません。

class Writer { 
    public static void doo(){
        System.out.println("sth");
    } 
}
class Author extends Writer{ 
    public void doo(){
        System.out.println("ok"); // error overridden method is static
    }
}

キーワードは、finalメソッドを呼び出すたびに特定のメソッド本体が実行されるようにします。これで、静的メソッドが同じ名前の子クラスで作成され、メソッドが呼び出されると、サブクラスのメソッドが実行されます。これは、親クラスの静的メソッド名の前にfinalが前に付いている場合は当てはまりません。 。したがって、finalキーワードは、子クラスでの同じ名前のメソッドの作成を制限します。

于 2018-11-26T10:21:55.040 に答える
0

静的メソッドは継承されたクラスに「隠され」ており、「非静的」にオーバーライドすることはできません。つまり、「ポリモーフィズム」の意味でオーバーライドすることはできません。ただし、「静的に」オーバーライドできます。

静的finalメソッドは、「静的」であってもオーバーライドできません。

次の例はこれを示しています-

App.java-

public class App {
    public static void main(String[] args) {
        Base.fun1();
        Base.fun2();
        Derived1.fun1();
        Derived1.fun2();
        Derived2.fun1();
        Derived2.fun2();
    }
}

Base.java-

public abstract class Base {

    protected static void fun1() {
        System.out.println("Static fun1() called in Base");
    }

    protected static final void fun2() {
        System.out.println("Static final fun2() called in Base");
    }

}

Derived1.java-

public class Derived1 extends Base {

    protected static void fun1() {
        System.out.println("Static fun1() called in Derived1");
    }
    
    //Not allowed to override final method
    /*
    protected static final void fun2() {
        System.out.println("Static final fun2() called in Derived1");
    }
    */
}

Derived2.java-

public class Derived2 extends Base {

    protected static void fun1() {
        System.out.println("Static fun1() called in Derived2");
    }
    
    //Not allowed to override final method
    /*
    protected static final void fun2() {
        System.out.println("Static final fun2() called in Derived2");
    }
    */
}

出力-

Static fun1() called in Base
Static final fun2() called in Base
Static fun1() called in Derived1
Static final fun2() called in Base
Static fun1() called in Derived2
Static final fun2() called in Base
于 2022-02-07T18:29:32.330 に答える