您的位置:首页 > 编程语言 > Java开发

再谈Java中的覆盖(Overriding)与重载(Overloading)

2018-03-06 18:59 459 查看
Overriding vs Overloading in Java 中,我们简单介绍了Java中的OverridingOverloading ,下面我们就此话题继续探讨:

问题一:什么是静态绑定?

答: 在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");
}**
}


子类 HoundOverride 父类中的 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)方法的访问修饰符 》= 父类方法访问修饰符

覆盖(Overriding)使用规范

方法参数完全一致
返回类型保持一致或者协变返回类型
访问修饰符子类访问修饰符大于等于父类访问修饰符
异常子类异常必须小于父类异常
构造方法无法覆盖
静态方法无法覆盖
final方法无法覆盖
重载(Overloading)使用规范

参数个数重载方法参数个数不同
参数类型重载方法参数类型不同
返回类型可以修改返回类型,但需注意重载情况不能出现方法签名相同但返回类型不同
参数顺序如果各个参数数据类型不同,那么参数顺序变化也是合法的方法重载
构造函数可以重载
原文链接:https://java2blog.com/method-overloading-and-overriding-interview-questions-in-java/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: