在 Overriding vs Overloading in Java 中,我们简单介绍了Java中的Overriding 与 Overloading ,下面我们就此话题继续探讨:
问题一:什么是静态绑定?
答: 在JAVA源码编译阶段,JVM将方法调用与实际方法进行绑定的过程,这就是静态绑定,我们常见的方法重载绑定( method Overloading binding )就是静态绑定。
问题二:什么是动态绑定?
答: 覆盖方法绑定(Binding of overridden methods)就是我们常见的动态绑定,即编译阶段只确定引用类型对象,运行时生成实际对象类型,并将对象引用指向运行时生成对象的内存堆地址。
问题三:你可以 override静态方法么?
答案:否,static方法属于类方法,属于类级别,而非对象实例级别,类方法是在类的加载机制的编译阶段就会执行的方法,我们上一章说过,Overriding涉及一个运行时概念,即我们常见的动态绑定机制,所以我们是无法通过Override静态方法来达到预期效果的。当然,如果你在子类中Override父类中相同方法签名的方法,编译期是不会报错的,但是却无法得到预期的Overriding行为的,下面我们示例说明:
父类 Dog 中定义静态方法 eat
class Dog {
public void bark() {
System.out.println("woof");
}
public void bark(int num) {
for (int i = 0; i < num; i++) {
System.out.println("woof");
}
}
**static void eat(){
System.out.println("Dog eat");
}**
}
子类 Hound 中 Override 父类中的 eat 方法
class Hound extends Dog {
public void bark() {
System.out.println("bowl");
}
static void eat(){
System.out.println("Hound eat");
}
}
验证对静态方法的 Override的效果
public class OverrideAndOverload {
public static void main(String[] args) {
Dog a = new Hound();
a.bark();
a.bark(1);
**a.eat();**
}
}
执行结果如下:
bowl
woof
Dog eat
从上面的执行结果我们可以看到,对静态方法的Override并没有达到预期效果,这就是我们常见的方法隐藏 method hiding
问题四:可以覆盖(Override)私有(private)方法和final方法么?
答:私有方法(private)对子类不可见,因此,你无法覆盖私有方法,final关键词修饰的方法或变量表明方法或变量不可变,即你无法重新修改目标对象,因此你无法覆盖(Override)方法
问题五:什么是协变返回类型?
答:如果子类中覆盖(overrides)了父类中的相关方法,那么子类方法的返回类型可以是父类方法中返回类型的子类,下面我们代码示例:
父类 Base 方法 m 返回类型为A,子类 Sub 覆盖了方法 m,但返回类型B(B是A的子类),这就是我们Overriding中的协变返回类型。
class A {
}
class B extends A {
}
class Base {
public A m() {
System.out.println("In BaseClass method");
return new A();
}
}
class Sub extends Base {
public B m() {
System.out.println("In SubClass method");
return new B();
}
}
public class CovariantReturnTypeTest {
public static void main(String[] args) {
Base b = new Sub();
b.m();
}
}
运行结果:
In SubClass method
问题六:以下代码输出结果?
import java.io.IOException;
public class MethodOverrdingTestMain {
public static void main(String[] args) {
B b = new B();
try {
b.method();
} catch (Exception e) {
e.printStackTrace();
}
}
}
class A {
public void method() **throws IOException** {
}
}
class B extends A {
public void method() **throws Exception** {
}
}
输出
**compile time error**
子类覆盖(Override)方法抛出的异常《= 父类方法抛出的异常,即子类抛出的异常可以缩小或不抛出异常,但不能新增或者扩大 **checked
Exception**
问题七:以下代码输出结果?
class Base {
**public** A m() {
System.out.println("In BaseClass method");
return new A();
}
}
class Sub extends Base {
**protected** B m() {
System.out.println("In SubClass method");
return new B();
}
}
public class CovariantReturnTypeTest {
public static void main(String[] args) {
Base b = new Sub();
b.m();
}
}
结果:
compiler time error
子类覆盖(Override)方法的访问修饰符 》= 父类方法访问修饰符
方法参数 | 完全一致 |
---|---|
返回类型 | 保持一致或者协变返回类型 |
访问修饰符 | 子类访问修饰符大于等于父类访问修饰符 |
异常 | 子类异常必须小于父类异常 |
构造方法 | 无法覆盖 |
静态方法 | 无法覆盖 |
final方法 | 无法覆盖 |
参数个数 | 重载方法参数个数不同 |
---|---|
参数类型 | 重载方法参数类型不同 |
返回类型 | 可以修改返回类型,但需注意重载情况不能出现方法签名相同但返回类型不同 |
参数顺序 | 如果各个参数数据类型不同,那么参数顺序变化也是合法的方法重载 |
构造函数 | 可以重载 |
原文链接:https://java2blog.com/method-overloading-and-overriding-interview-questions-in-java/