简体   繁体   English

为什么静态方法不涉及多态(后期绑定)我看到错误,静态方法不能被覆盖

[英]Why if static method don't involve in polymorphism(late binding) I see error that static method cannot be overridden

please consider following code: 请考虑以下代码:

class A{
    public static void m(Number n){
         System.out.println("Number A");
    };
}
class B extends A{
     public static int m(Number n){
        System.out.println("Number B");
        return 1;
      };
}

output: 输出:

java: m(java.lang.Number) in inheritanceTest.B cannot override m(java.lang.Number) in inheritanceTest.A return type int is not compatible with void java中的:inheritanceTest.B中的m(java.lang.Number)不能覆盖inheritanceTest中的m(java.lang.Number)。返回类型int与void不兼容

I know that static methods doen't involve in polymorphism hence I infer that overriding is impossible for my code. 我知道静态方法不涉及多态,因此我推断我的代码不可能覆盖。 This compiler message is strange for me. 这个编译器消息对我来说很奇怪。

As I understand that overriding is part of polymorphism. 据我所知,重写是多态的一部分。 I prepare for scjp and I am afraid make mistake in familiar question. 我准备scjp,我害怕在熟悉的问题上犯错误。

Please clarify this issue. 请澄清这个问题。

expected behaviour for me - message about overloading error 我的预期行为 - 有关重载错误的消息

P.S1. P.S1。

I have read top popular question about static overridden and I didn't found answer( 我已经阅读了关于静态覆盖的最受欢迎的问题,我没有找到答案(

P.S2. P.S2。 According Pshemo answer: 据Pshemo回答:

this code: 这段代码:

class Foo{
    public static void m(Number n){
         System.out.println("Number A");
    };
    public static int m(Number n){
        System.out.println("Number B");
        return 1;
    };
}

outputs: 输出:

error: method m(Number) is already defined in class Foo
    public static int m(Number n){
                      ^
1 error

For me these situations are same. 对我来说,这些情况是一样的。 But compiler error is different - strange. 但编译器错误不同 - 很奇怪。

Even if static methods can't be overridden they are still inherited so what you are trying to do would lead to situation similar to 即使静态方法无法被覆盖,它们仍然是继承的,所以你要做的事情会导致类似的情况

class Foo{
    public static void m(Number n){
         System.out.println("Number A");
    };
    public static int m(Number n){
        System.out.println("Number B");
        return 1;
    };
}

which is wrong because you can't have two methods with same signature but with different return types. 这是错误的,因为你不能有两个具有相同签名但具有不同返回类型的方法。 Reason why it was forbidden is quite simple... Lets say we have methods: 它被禁止的原因很简单......让我们说我们有方法:

  • Foo method(){ return new Foo(); }
  • Bar method(){ return new Bar(); }

and you would want to invoke them like 你会想要像他们一样调用它们

System.out.println(method());

Should result be Foo or Bar? 结果应该是Foo还是Bar? Compiler wouldn't be able to decide. 编译器无法决定。

To prevent this kind of situations compiler forbids overriding/hiding methods with same signature by changing its return types. 为了防止这种情况,编译器通过更改其返回类型来禁止覆盖/隐藏具有相同签名的方法。 Only exception is when you are changing return type to more detailed one like 唯一的例外是当您将返回类型更改为更详细的类型时

class X{
    List<String> m(){...}
}

class Y extends X{
    LinkedList<String> m(){...}
}

So it seems that override is not best word here. 因此, override似乎不是最好的词。 Correct word should be hide since static methods can be hidden, not overridden. 应该hide正确的单词,因为静态方法可以隐藏,而不是被覆盖。 But it looks like same rules (or at least some portion of them) are used to test if we can hide method as rules for overriding, so in case of problem same error message is shown (about overriding instead of hiding), which can be misleading. 但它看起来像是相同的规则(或至少它们的一部分)用于测试我们是否可以将方法隐藏为覆盖规则,因此在出现问题时会显示相同的错误消息(关于覆盖而不是隐藏),这可能是误导。

JLS §8.4.8.3 (Java 8) says: JLS§8.4.8.3(Java 8)说:

If a method declaration d 1 with return type R 1 overrides or hides the declaration of another method d 2 with return type R 2 , then d 1 must be return-type-substitutable (§8.4.5) for d 2 , or a compile-time error occurs. 如果一个方法声明d 1与返回类型的R 1所 覆盖或隐藏的另一方法d 2与返回类型中的R 2的声明,则d 1必须返回型取代(§8.4.5)为d 2,或编译发生时间错误。

This same rule applies both to instance methods and static methods, since it says "overrides or hides". 同样的规则同时适用于实例方法和静态方法,因为它表示“覆盖或隐藏”。 Basically, if you have a method with the same name and same parameters, it overrides if it's an instance method, but hides (the inherited method) if it's a class (static) method. 基本上,如果你有一个具有相同名称和相同参数的方法,它会覆盖它是一个实例方法,但如果它是一个类(静态)方法则隐藏(继承方法)。 And in both cases, the return type must either be the same or obey the rules for covariance. 在这两种情况下,返回类型必须相同或遵守协方差规则。

Since it's the same rule, most likely there's just one place in the compiler code that checks this rule, and if the rule is violated you're getting the error you're seeing, which I'm sure is a much more common occurrence. 由于它是相同的规则,很可能在编译器代码中只有一个地方检查此规则,如果规则被违反,您将收到您正在看到的错误,我确信这是更常见的情况。 The compiler really should check to see whether it should say "overrides" or "hides", but it looks like they slipped. 编译器确实应该检查是否应该说“覆盖”或“隐藏”,但看起来它们会滑落。 Getting error message exactly right is not usually the highest priority of compiler writers--not compared to making sure code that's supposed to compile does so and runs right, and code that isn't supposed to compile doesn't. 完全正确地获取错误消息通常不是编译器编写者的最高优先级 - 与确保编译应该编译的代码并运行正确,而不应该编译的代码不相比。 So I think this is a deficiency, but a very minor one. 所以我认为这是一个缺陷,但非常小。

I think the compiler error usage of 'override' is misleading here, it isn't applicable. 我认为'覆盖'的编译器错误用法在这里有误导性,它不适用。

The language spec says: 语言规范说:

If a method declaration d1 with return type R1 overrides or hides the declaration of another method d2 with return type R2, then d1 must be return-type substitutable for d2, or a compile-time error occurs. 如果具有返回类型R1的方法声明d1覆盖或隐藏具有返回类型R2的另一个方法d2的声明,则d1必须是d2的return-type substitutable,否则会发生编译时错误。

Here your B method is hiding the declaration of Am: 这里你的B方法隐藏了Am的声明:

If a class declares a static method m, then the declaration m is said to hide any method m', where the signature of m is a subsignature (§8.4.2) of the signature of m', in the superclasses and superinterfaces of the class that would otherwise be accessible to code in the class. 如果一个类声明了静态方法m,则声明m被称为隐藏任何方法m',其中m的签名是m'签名的子签名(第8.4.2节),在超类和超接口中。该类中的代码可以访问的类。

If your B class did not have an m method, then you could call Bm and it would call the m defined on A. 如果你的B类没有m方法,那么你可以调用Bm,它会调用A上定义的m。

Having Bm is hiding A's version of m. 让Bm隐藏A的m版本。 Because you can call a static method defined on a superclass but reference the subclass, that sets up some expectations about the method that are violated by the different return type. 因为您可以调用在超类上定义的静态方法但引用子类,这会设置对不同返回类型违反的方法的一些期望。

It's hiding and not overriding because if you have a Bm defined, you can still call Am and get the superclass' version of the method. 它隐藏而不是覆盖,因为如果你定义了Bm,你仍然可以调用Am并获得该方法的超类版本。 With overriding it's the runtime type that decides what gets called and how it's called does not matter. 覆盖它的运行时类型决定了被调用的内容以及它的调用方式并不重要。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 以下代码是否将后期绑定应用于 static 方法? 多态性 Java - Did this following code apply late binding onto a static method? Polymorphism Java 为什么我不需要在构造方法中使用 static? - Why I don´t need to use static in my constructor method? 阐述:方法重载是静态/编译时绑定,但不是多态。 将静态绑定与多态相关联是否正确? - Elaboration: Method overloading is a static/compile-time binding but not polymorphism. Is it correct to correlate static binding with polymorphism? 收到“无法对非静态方法进行静态引用”错误,但我尚未将要从中调用的方法声明为静态方法 - getting “cannot make a static reference to the non-static method” error, but I haven't declared the method I'm calling from as static 为什么toString()不能是静态方法? - Why toString() cannot be a static method? 日食。 如果没有无法访问代码的方法没有调用,为什么我看不到编译错误? - Eclipse. Why don't I see compile error if method with unreachable code doesn't invoke? 为什么不是每个方法都是 static 方法? - Why isn't every method is a static method? Java8:当引用的方法不是静态的时,为什么引用的方法不能编译? - Java8: Why the reference method don't compile when the referenced method isn't static? java静态绑定和多态 - java static binding and polymorphism Java:静态方法无法识别重写的compareTo() - java: overridden compareTo() not recognized in static method
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM