简体   繁体   English

Java 重载和覆盖的方法

[英]Java Overloaded AND Overridden Methods

In the following program, I have one single method in class A overloaded 3 times and then in subclass B, all 3 overloaded methods are overridden.在下面的程序中,我在 class A 中有一个方法重载了 3 次,然后在子类 B 中重载了所有 3 个重载方法。

obj3 is an object with reference type A(superclass) and object type B(subclass) and it calls the method from B on execution, which is expected behavior. obj3 是一个 object 引用类型 A(超类)和 object 类型 B(子类),它在执行时调用 B 的方法,这是预期的行为。

Since overloading and overriding both exist in this code, does that mean that it performed static binding at compile time (to the matching method in class A) and then dynamic binding at run time (to method in class B).由于这段代码中同时存在重载和覆盖,是否意味着它在编译时执行了 static 绑定(到 class A 中的匹配方法),然后在运行时动态绑定(到 class B 中的方法)。 Can they both occur together?它们可以同时发生吗?

My assumption is that this is a classic case of dynamic binding as I believed "binding" is meant to be a permanent action, but a peer suggests that it is both together(static first, then dynamic).我的假设是,这是动态绑定的经典案例,因为我认为“绑定”是一种永久性行为,但同行建议它是一起的(首先是静态的,然后是动态的)。

class A{
    
    public void method(Integer n){
        System.out.println("Integer: "+n);
    }
    
    public void method(String s){
        System.out.println("String: "+s);
    }
    
    public void method(String s, Integer n){
        System.out.println("String: "+s+" Integer: "+n);
    }
}

class B extends A{
    
    public void method(Integer n){
        System.out.println("Integer(from B): "+n);
    }
    
    public void method(String s){
        System.out.println("String(from B): "+s);
    }
    
    public void method(String s, Integer n){
        System.out.println("String(from B): "+s+" Integer(from B): "+n);
    }
}

public class Test{
    public static void main(String[] args){
        A obj1 = new A();
        B obj2 = new B();
        A obj3 = new B();
        
        System.out.println("Integer form of method");
        // Integer form of method

        System.out.println("Ref A Obj A");
        // Ref A Obj A
        obj1.method(1);
        // Integer: 1
        
        System.out.println("Ref B Obj B");
        // Ref B Obj B
        obj2.method(2);
        // Integer(from B): 2
        
        System.out.println("Ref A Obj B");
        // Ref A Obj B
        obj3.method(3);
        // Integer(from B): 3
        
    }
}

You right.你说得对。 Compiler is statically choose between overloads in class A and put that information into .class file in form of method FQN.编译器在 class A中的重载之间进行静态选择,并将该信息以方法 FQN 的形式放入.class文件中。

Then runtime dynamically choose between implementation of that method.然后运行时在该方法的实现之间动态选择。

Since overloading and overriding both exist in this code, does that mean that it performed static binding at compile time (to the matching method in class A) and then dynamic binding at run time (to method in class B)由于这段代码中同时存在重载和覆盖,是否意味着它在编译时执行了 static 绑定(到 class A 中的匹配方法),然后在运行时动态绑定(到 class B 中的方法)

Right.正确的。 The compiler chose the matching signature, and this is static, based on the type of the variable ( A in this case).编译器根据变量的类型(在本例中为A )选择了匹配的签名,即 static。

At runtime, Java finds the implementation of the signature selected by the compiler.在运行时,Java 找到编译器选择的签名的实现。 This is dynamic, based on the runtime class of obj3 ( B , in this case).这是动态的,基于obj3 (在本例中为B )的运行时 class。

One more attempt to make it clear:再一次尝试说清楚:

Overloading重载

Overloading means that a single class has multiple methods with different parameter types (aka. signatures), and you just happened to give them the same name.重载意味着单个 class 具有多个具有不同参数类型(又名签名)的方法,而您恰好为它们指定了相同的名称。 Your program will work the very same if you change to individual names for the methods, eg methodI(Integer n) , methodS(String s) , and methodSI(String s, Integer n) .如果您将方法更改为单独的名称,例如 methodI methodI(Integer n)methodS(String s)methodSI(String s, Integer n)您的程序将以完全相同的方式工作。

Or, you can imagine the compiler to internally always append such a types list to the method name.或者,您可以想象编译器在内部总是将 append 这样的类型列表添加到方法名称中。

Overloading is resolved by the compiler, based on the compile-time types of the parameter expressions .重载由编译器根据参数表达式编译时类型解决。

Eg if you write例如,如果你写

Object par = "Test";
a.method(par);

you get a compiler error.你得到一个编译器错误。 Even though we all see it's a String that you are passing into the method, the compiler only sees an Object , and finds no matching method.尽管我们都看到您传递给方法的是一个String ,但编译器只看到一个Object ,并且找不到匹配的方法。 Only if you were to introduce an additional method(Object o) , the compiler would choose that one.只有当你要引入一个额外的method(Object o)时,编译器才会选择那个。 And runtime would call that method and not the String version !运行时会调用该方法而不是 String 版本

Overriding覆盖

Overriding means that at runtime the JVM calls the method implementation depending on the runtime class of the "object before the dot" .覆盖意味着在运行时 JVM根据“点之前的对象”的运行时 class 调用方法实现。

And in this case, "method" is to be read as the overloaded method version that the compiler found to match the parameter list.在这种情况下,“方法”将被读取为编译器找到的与参数列表匹配的重载方法版本。 So, runtime already knows whether methodI() , methodS() , or methodSI() is meant, and only decides from which class to take the implementation.因此,运行时已经知道是 methodI( methodI()methodS()还是methodSI()的意思,并且只决定从哪个 class 中获取实现。

Personal opinion个人观点

Allowing multiple methods to share the same name, but differ in parameter lists (aka overloading), produces too much confusion for its benefit.允许多个方法共享相同的名称,但参数列表不同(又名重载),会产生太多的混乱。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM