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

余生颓废 提交于 2019-12-05 23:03:32

问题


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

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.

Please clarify this issue.

expected behaviour for me - message about overloading error

P.S1.

I have read top popular question about static overridden and I didn't found answer(

P.S2. According Pshemo answer:

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.


回答1:


JLS §8.4.8.3 (Java 8) says:

If a method declaration d1 with return type R1overrides or hides the declaration of another method d2 with return type R2, then d1 must be return-type-substitutable (§8.4.5) for d2, or a compile-time error occurs.

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.




回答2:


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? 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. Correct word should be hide since static methods can be hidden, not overridden. 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.




回答3:


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.

Here your B method is hiding the declaration of A.m:

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.

If your B class did not have an m method, then you could call B.m and it would call the m defined on A.

Having B.m is hiding A's version of 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 B.m defined, you can still call A.m and get the superclass' version of the method. With overriding it's the runtime type that decides what gets called and how it's called does not matter.



来源:https://stackoverflow.com/questions/23573726/why-if-static-method-dont-involve-in-polymorphismlate-binding-i-see-error-tha

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!