Java 最终静态方法的行为

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1743715/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 22:09:07  来源:igfitidea点击:

Behaviour of final static method

javamethodsstaticfinal

提问by Harish

I have been playing around with modifiers with static method and came across a weird behaviour.

我一直在玩带有静态方法的修饰符,并遇到了一个奇怪的行为。

As we know, static methods cannot be overridden, as they are associated with class rather than instance.

正如我们所知,静态方法不能被覆盖,因为它们与类而不是实例相关联。

So if I have the below snippet, it compiles fine

所以如果我有下面的代码片段,它编译得很好

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

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

But if I include final modifier to static method in class A, then compilation fails ts() in B cannot override ts() in A; overridden method is static final.

但是如果我在类 A 的静态方法中包含 final 修饰符,那么编译失败 B 中的 ts() 不能覆盖 A 中的 ts();重写的方法是 static final

Why is this happening when static method cannot be overridden at all?

为什么在根本无法覆盖静态方法时会发生这种情况?

采纳答案by NawaMan

Static methods cannot be overridden but they can be hidden. The ts()method of B is not overriding(not subject to polymorphism) the ts()of A but it will hide it. If you call ts()in B (NOT A.ts()or B.ts()... just ts()), the one of B will be called and not A. Since this is not subjected to polymorphism, the call ts()in A will never be redirected to the one in B.

静态方法不能被覆盖,但它们可以被隐藏。ts()B的方法不会覆盖(不受多态性影响)ts()A 的方法,但它会隐藏它。如果您调用ts()B(NOTA.ts()B.ts()... just ts()),将调用 B 中的一个而不是 A。由于这不受多态性的影响,因此ts()A 中的调用永远不会重定向到 B 中的一个。

The keyword finalwill disable the method from being hidden. So they cannot be hidden and an attempt to do so will result in a compiler error.

该关键字final将禁止隐藏该方法。因此它们不能被隐藏,并且尝试这样做会导致编译器错误。

Hope this helps.

希望这可以帮助。

回答by Vincent Ramdhanie

static methods cannot be overriden

静态方法不能被覆盖

This is not exactly true. The example code really means that the method ts in B hides the method ts in A. So its not exactly overriding. Over on Javaranchthere is a nice explanation.

这并不完全正确。示例代码实际上意味着 B 中的方法 ts 隐藏了 A 中的方法 ts。所以它不是完全覆盖。在Javaranch 上有一个很好的解释。

回答by amischiefr

The ts() method in B is not overriding the ts() method in A, it simply is another method. The B class does not see the ts() method in A since it is static, therefore it can declare its own method called ts().

B 中的 ts() 方法没有覆盖 A 中的 ts() 方法,它只是另一种方法。B 类在 A 中看不到 ts() 方法,因为它是静态的,因此它可以声明自己的方法,称为 ts()。

However, if the method is final, then the compiler will pick up that there is a ts() method in A that should not be overridden in B.

但是,如果该方法是最终的,那么编译器会发现 A 中有一个 ts() 方法不应在 B 中被覆盖。

回答by Powerlord

Static methods belong to the class, not the instance.

静态方法属于类,而不是实例。

A.ts()and B.ts()are always going to be separate methods.

A.ts()并且B.ts()总是将是单独的方法。

The real problem is that Java lets you call static methods on an instance object. Static methods with the same signature from the parent class are hiddenwhen called from an instance of the subclass. However, you can't override/hide final methods.

真正的问题是 Java 允许您在实例对象上调用静态方法。从子类的实例调用时,父类中具有相同签名的静态方法将被隐藏。但是,您不能覆盖/隐藏final methods

You would think the error message would use the word hidden instead of overridden...

你会认为错误消息会使用隐藏而不是覆盖这个词......

回答by BalusC

I think the compilation error was quite misleading here. It should not have said "overridden method is static final.", but it should instead have said "overridden method is final.". The static modifier is irrelevant here.

我认为编译错误在这里非常具有误导性。它不应该说“被覆盖的方法是静态最终的。”,而应该说“被覆盖的方法是最终的。”。静态修饰符在这里无关紧要。

回答by Mathias Bader

You might find yourself in the position to think about making a static method final, considering the following:

您可能会发现自己可以考虑将静态方法设为 final,请考虑以下几点:

Having the following classes:

有以下课程:

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

Now the 'correct' way to call these methods would be

现在调用这些方法的“正确”方法是

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

which would result in ABbut you could also call the methods on instances:

这将导致AB但您也可以在实例上调用方法:

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

which would result in ABas well.

这也会导致AB

Now consider the following:

现在考虑以下几点:

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

that would print A. That might surprise you since you are actually having an object of class B. But since you're calling it from a reference of type A, it will call A.ts(). You could print Bwith the following code:

那会打印A. 这可能会让您感到惊讶,因为您实际上拥有一个 class 对象B。但是由于您是从 type 的引用中调用它A,因此它将调用A.ts(). 您可以B使用以下代码打印:

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

In both cases the object you have is actually from class B. But depending on the pointer that points to the object, you will call method from Aor from B.

在这两种情况下,您拥有的对象实际上来自 class B。但是根据指向对象的指针,您将调用方法 fromA或 from B

Now let's say you are the developer of class Aand you want to allow sub-classing. But you really want method ts(), whenever called, even from a subclass, that is does what you want it to do and not to be hidden by a subclass version. Then you could make it finaland prevent it from being hidden in the subclass. And you can be sure that the following code will call the method from your class A:

现在假设您是类的开发者,A并且您希望允许子类化。但是您确实想要 method ts(),无论何时调用,即使是从子类调用,也就是执行您希望它执行的操作,并且不会被子类版本隐藏。然后你可以制作它final并防止它隐藏在子类中。您可以确定以下代码将从您的类中调用该方法A

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

Ok, admittetly that is somehow constructed, but it might make sense for some cases.

好的,无可否认,这是以某种方式构建的,但在某些情况下可能有意义。

You should not call static methods on instances but directly on the classes - then you won't have that problem. Also IntelliJ IDEA for example will show you a warning, if you call a static method on an instance and as well if you make a static method final.

你不应该在实例上调用静态方法,而应该直接在类上调用 - 那么你就不会有那个问题了。例如,IntelliJ IDEA 也会向您显示警告,如果您在实例上调用静态方法,并且将静态方法设为 final。

回答by Pratik Gupta

A static method can't be overridden in Java, unlike non-static methods. But they are inherited like static and non-static data members. That is why a non-static method with the same name can't be created in the parent class

与非静态方法不同,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
    }
}

The finalkeyword ensures that the specific method body be run everytime a call to the method. Now if a static method is created in the child class with the same name and a call to the method is made, the method in the subclass gets executed which should not be the case if final is prefixed before the static method name in the parent class. Hence final keyword restricts the creation of method with the same name in the child class.

final关键字确保了特定方法主体运行每次对方法的调用。现在,如果在子类中创建了一个同名的静态方法并调用了该方法,则子类中的方法将被执行,如果在父类中的静态方法名称之前加上 final 前缀,则不应出现这种情况. 因此 final 关键字限制在子类中创建同名方法。