面试题答案
一键面试方法重载(Overloading)
- 本质区别:
- 方法重载是指在同一个类中,方法名相同,但参数列表不同(参数个数、类型或顺序不同)。它是一种编译时多态性。
- 字节码指令体现:
- 编译后,对于重载的方法,在字节码层面,它们具有不同的方法签名。方法签名包括方法名和参数列表。例如,假设有一个类
OverloadExample
:
- 编译后,对于重载的方法,在字节码层面,它们具有不同的方法签名。方法签名包括方法名和参数列表。例如,假设有一个类
public class OverloadExample {
public void method(int i) {}
public void method(String s) {}
}
- 编译后,在字节码文件中,这两个
method
方法通过不同的参数类型来区分。例如,对于method(int i)
方法,字节码中的方法签名可能是method(I)V
,其中I
表示int
类型参数,V
表示返回值为void
;对于method(String s)
方法,方法签名可能是method(Ljava/lang/String;)V
,Ljava/lang/String;
表示String
类型参数。
- 对绑定机制的影响:
- 由于方法重载在编译时就根据参数列表确定调用哪个方法,所以它使用静态绑定机制。在编译阶段,编译器就能明确知道要调用哪个重载版本的方法。例如:
OverloadExample oe = new OverloadExample();
oe.method(10); // 编译时就确定调用 method(int i)
方法重写(Overriding)
- 本质区别:
- 方法重写是指子类中定义了与父类中方法签名完全相同(方法名、参数列表和返回类型相同,Java 5.0 后返回类型可以是父类方法返回类型的子类)的方法。它是一种运行时多态性。
- 字节码指令体现:
- 对于重写的方法,在字节码层面,子类和父类中重写方法的方法签名是相同的。例如,假设有父类
Animal
和子类Dog
:
- 对于重写的方法,在字节码层面,子类和父类中重写方法的方法签名是相同的。例如,假设有父类
class Animal {
public void makeSound() {}
}
class Dog extends Animal {
@Override
public void makeSound() {}
}
- 在字节码中,
Animal
类和Dog
类的makeSound
方法签名都是makeSound()V
。但是,在子类的字节码中,会通过ACC_OVERRIDE
标志来标记该方法为重写方法。
- 对绑定机制的影响:
- 方法重写使用动态绑定机制。在运行时,JVM 根据对象的实际类型来确定调用哪个重写版本的方法。例如:
Animal animal1 = new Animal();
Animal animal2 = new Dog();
animal1.makeSound(); // 调用 Animal 类的 makeSound 方法
animal2.makeSound(); // 运行时根据 animal2 实际指向的 Dog 对象,调用 Dog 类的 makeSound 方法
- 在字节码层面,对于重写方法的调用,使用
invokevirtual
指令。该指令在运行时根据对象的实际类型来动态查找并调用合适的方法。例如,对于animal2.makeSound()
的调用,字节码中会有invokevirtual
指令,在运行时,JVM 会根据animal2
实际指向的Dog
对象,找到Dog
类中的makeSound
方法并执行。
综上所述,方法重载基于编译时参数列表的不同实现静态绑定,通过不同的方法签名在字节码中区分;方法重写基于运行时对象的实际类型实现动态绑定,字节码中通过相同的方法签名和 ACC_OVERRIDE
标志体现,调用时使用 invokevirtual
指令。