Calling overloaded inherited methods using super c

2020-02-25 07:39发布

I do not understand this Java behavior. I have two classes:

class C1 {
    public void m1(double num) {
        System.out.println("Inside C1.m1(): " + num);
    }
}

class C2 extends C1 {
    public void m1(int num) {
        System.out.println("Inside C2.m1(): " + num);
    }
}

And it is my main:

public class Main {

    public static void main(String[] args) {
        C1 c = new C2();
        c.m1(10);
    }
}

And the result was:

Inside C1.m1(): 10.0

When I expected:

Inside C2.m1(): 10

Also when I try to complete the code syntax, I found this:

Enter image description here

Where is the other m1 of C2 class?

I also check the bytecode of my Main.class and I saw this:

Compiled from "Main.java"
public class com.company.Main {
  public com.company.Main();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class com/company/C2
       3: dup
       4: invokespecial #3                  // Method com/company/C2."<init>":()V
       7: astore_1
       8: aload_1
       9: ldc2_w        #4                  // double 10.0d
      12: invokevirtual #6                  // Method com/company/C1.m1:(D)V
      15: return
}

The bytecode tell me that it will invoke the C1.m1 (D)V (line 12).

Why the method of C1? I am trying to understand this behavior.

10条回答
男人必须洒脱
2楼-- · 2020-02-25 08:12

Java chooses the most specific applicable type. In this case m1(int) is not applicable. Emphasis on the reference of class that hold object of same class(c1) or an object of any sub classes of class(c2) & method name and parameter list .

Your method with double parameters is being called because double takes priority over int. This is because an int can be assigned to a double, but not the other way around.

So there are so many things to be consider at the (run) time of method call.

Yes for ur case your main class should be like this

        public static void main(String[] args) {
            C1 c = new C2();
            c.m1(10);
            ((C2) c).m1(10);
    //or
            C2 cobj = new C2();
            cobj.m1(10);
        }


**OutPut**
Inside C1.m1(): 10.0
Inside C2.m1(): 10
Inside C2.m1(): 10
查看更多
Anthone
3楼-- · 2020-02-25 08:19

If you call c.m1(10.0) it will call the method of the ancestor as you were expecting at first.

You're doing method overloading in your example (that is adding more methods with the same name and different signature) instead of method overriding (that is changing the implementation of an ancestor's method at a descendent by redeclaring it with the same signature, AKA same name and same type of result and of method arguments - argument names shouldn't matter).

查看更多
我想做一个坏孩纸
4楼-- · 2020-02-25 08:20

Java does method dispatch on static types, and your variable c is of type C1, so m1(int) is not visible, and your 10 is cast to double.

查看更多
爱情/是我丢掉的垃圾
5楼-- · 2020-02-25 08:21

Your two methods named m1 do not have the same signature; the one in the superclass takes a double, and the one in the subclass takes an int. This means that the compiler will select the method signature to call based on the compile-time type of your variable, which is C1, and will call m1(double). Since at runtime the class C2 doesn't have an overriding version of m1(double), the version from C1 is invoked.

The rule is that method signatures are computed at compile time based on compile-time types; method calls are dispatched at runtime based on matching signatures.

查看更多
Melony?
6楼-- · 2020-02-25 08:24

It's because of the parameters. The method you call is a method with a double parameter. m1 inside of C2 is not overriding this, instead it's overLOADING it.

If you want to call m1 in C2, you have to cast the reference such that the compiler accepts what you're doing.

查看更多
孤傲高冷的网名
7楼-- · 2020-02-25 08:28

You cannot see methods of C2, because you instance variable is declared as C1 and also because they don't have the same signature. You have double parameter in one method and in second a int type which makes them for JVM completely different methods (so no inheritance will work here).

So if you have int type in C1 method then you need to have also int type in C2 method, then JVM will run method from C2 like you wanted.

Also you can cast variable to C2 type then you will be able to access to methods of C2.

查看更多
登录 后发表回答