Java JVM如何在内部区分方法重载和方法重写?
我想知道JVM在内部是如何区分方法重载和方法重写的。尽管方法重载和重写的名称保持不变,但主要区别在于方法重载是在编译时解决的,而方法重写是在运行时解决的。在Java中重写或重载方法的规则也不同。例如,private、static和final方法在Java中不能被重写,但您仍然可以重载它们。对于重写,方法的名称和签名必须保持相同,但对于重载,方法签名必须不同。最后但并非最不重要的区别是,在Java中,对重载方法的调用是使用静态绑定解决的,而对重写方法的调用是使用动态绑定解决的。因此JVM不涉及重载Java JVM如何在内部区分方法重载和方法重写?,java,Java,我想知道JVM在内部是如何区分方法重载和方法重写的。尽管方法重载和重写的名称保持不变,但主要区别在于方法重载是在编译时解决的,而方法重写是在运行时解决的。在Java中重写或重载方法的规则也不同。例如,private、static和final方法在Java中不能被重写,但您仍然可以重载它们。对于重写,方法的名称和签名必须保持相同,但对于重载,方法签名必须不同。最后但并非最不重要的区别是,在Java中,对重载方法的调用是使用静态绑定解决的,而对重写方法的调用是使用动态绑定解决的。因此JVM不涉及重载
方法重载: 方法重写:
中的Jvm不涉及方法重载。因此,它不必区分方法重载和方法重写 如果您了解Java是如何在幕后实现方法重载和方法重写的,您就会清楚地理解这一点。 在讨论重载和重写之间的区别之前,让我们先看看多态性 什么是多态性? 多态性是一种方法根据其作用的对象执行不同操作的能力。换句话说,多态性允许您定义一个接口并有多个实现 java中不同类型的多态性。 1) 方法重载 2) 方法重写 java中的多态类型:静态、动态、运行时和编译时 现在让我们回到原来的问题,理解重载和重写之间的区别 1。第一个也是最重要的是,方法重载编译时多态性,而方法重写是运行时多态性。所以JVM只需要处理方法重写。编译后已解决方法重载问题。 2.在方法重载中,方法必须具有不同的签名。在方法重写中,方法必须具有相同的签名。 还有很多不同之处,但以上两种方法确实可以区分方法重载和方法重写 在结束之前,让我们也看看每个人都在努力实现什么
方法重载是对方法的行为进行更多的“添加”或“扩展”。方法重写是“更改”方法的现有行为。JVM只处理方法重写。通过在派生类中添加具有相同签名的方法来重写方法(唯一允许的差异是返回类型,它允许更具体)。签名对方法名称、参数类型和返回类型进行编码
方法重载意味着有多个具有相同“简单名称”但签名不同的方法。编译时,
javac
编译器根据参数的类型选择一个相同的命名方法,并将其签名放在编译后的.class
文件中。编译后的Java字节码中的方法调用必须指定被调用方的签名。方法重载由编译器处理(这就是为什么称为静态绑定),而重写由JVM处理
重载方法是不同的,并且可以根据参数列表单独识别,这就是为什么编译器在编译时解析重载方法
方法重写发生在我们试图对持有子对象的父对象
引用调用重写的方法时。因为我们在parent
reference上调用方法,所以在编译时方法从parent
reference类型得到解析,所以对于编译器,调用parent
的方法。但是parent
持有child
的对象,因此在运行时从child
调用方法
为了理解Java(编译器+JVM)如何在内部处理这两件事,让我们以哺乳动物和人类类为例
public class OverridingInternalExample {
private static class Mammal {
public void speak() { System.out.println("ohlllalalalalalaoaoaoa"); }
}
private static class Human extends Mammal {
@Override
public void speak() { System.out.println("Hello"); }
// Valid overload of speak
public void speak(String language) {
if (language.equals("Hindi")) System.out.println("Namaste");
else System.out.println("Hello");
}
@Override
public String toString() { return "Human Class"; }
}
// Code below contains the output and bytecode of the method calls
public static void main(String[] args) {
Mammal anyMammal = new Mammal();
anyMammal.speak(); // Output - ohlllalalalalalaoaoaoa
// 10: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V
Mammal humanMammal = new Human();
humanMammal.speak(); // Output - Hello
// 23: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V
Human human = new Human();
human.speak(); // Output - Hello
// 36: invokevirtual #7 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:()V
human.speak("Hindi"); // Output - Namaste
// 42: invokevirtual #9 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:(Ljava/lang/String;)V
}
}
当我们编译上述代码并尝试使用javap-verbose OverridingInternalExample
查看字节码时,我们可以看到编译器生成一个常量表,在该表中为每个方法调用分配整数代码
我已经包括了字节码和上面的方法调用,通过查看上面的代码,我们可以看到人类哺乳动物说话()
,人类说话()
和人类说话(“印地语”)的字节码
完全不同,因为编译器能够根据参数列表和类引用区分它们。这就是方法重载被称为静态多态性或静态绑定的原因
但是任何哺乳动物.speak()和人类哺乳动物.speak()的字节码
是相同的,因为根据编译器,这两个方法都是在哺乳动物
引用上调用的,但是两个方法调用的输出是不同的,因为在运行时JVM知道引用所持有的对象,JVM调用对象上的方法,这就是为什么方法重写被称为动态的原因多态性或简单的多态性
如果您想了解更多这方面的信息,可以阅读更多。重载是编译时功能。JVM不参与其中。用@SotiriosDelimanolis一行简单而最好的答案!!
class Calculation{
void sum(){System.out.println("sum in superclass");}
}
class Specific extends Calculation{
void sum(){System.out.println("sum in Specific");}
}
public class OverridingInternalExample {
private static class Mammal {
public void speak() { System.out.println("ohlllalalalalalaoaoaoa"); }
}
private static class Human extends Mammal {
@Override
public void speak() { System.out.println("Hello"); }
// Valid overload of speak
public void speak(String language) {
if (language.equals("Hindi")) System.out.println("Namaste");
else System.out.println("Hello");
}
@Override
public String toString() { return "Human Class"; }
}
// Code below contains the output and bytecode of the method calls
public static void main(String[] args) {
Mammal anyMammal = new Mammal();
anyMammal.speak(); // Output - ohlllalalalalalaoaoaoa
// 10: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V
Mammal humanMammal = new Human();
humanMammal.speak(); // Output - Hello
// 23: invokevirtual #4 // Method org/programming/mitra/exercises/OverridingInternalExample$Mammal.speak:()V
Human human = new Human();
human.speak(); // Output - Hello
// 36: invokevirtual #7 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:()V
human.speak("Hindi"); // Output - Namaste
// 42: invokevirtual #9 // Method org/programming/mitra/exercises/OverridingInternalExample$Human.speak:(Ljava/lang/String;)V
}
}