天道不一定酬所有勤
但是,天道只酬勤
Hollis出品的全套Java面试宝典不来了解一下吗?

深入理解Java中的重写和重载

Hollis出品的全套Java面试宝典不来了解一下吗?

overloading-vs-overriding

重载(Overloading)和重写(Overriding)是Java中两个比较重要的概念。但是对于新手来说也比较容易混淆。本文通过两个简单的例子说明了他们之间的区别。

定义

重载

简单说,就是函数或者方法有同样的名称,但是参数列表不相同的情形,这样的同名不同参数的函数或者方法之间,互相称之为重载函数或者方法。

重写

重写指的是在Java的子类与父类中有两个名称、参数列表都相同的方法的情况。由于他们具有相同的方法签名,所以子类中的新方法将覆盖父类中原有的方法。

重载 VS 重写

关于重载和重写,你应该知道以下几点:

1、重载是一个编译期概念、重写是一个运行期间概念。

2、重载遵循所谓“编译期绑定”,即在编译时根据参数变量的类型判断应该调用哪个方法。

3、重写遵循所谓“运行期绑定”,即在运行的时候,根据引用变量所指向的实际对象的类型来调用方法

4、因为在编译期已经确定调用哪个方法,所以重载并不是多态。而重写是多态。重载只是一种语言特性,是一种语法规则,与多态无关,与面向对象也无关。(注:严格来说,重载是编译时多态,即静态多态。但是,Java中提到的多态,在不特别说明的情况下都指动态多态)

重写的例子

下面是一个重写的例子,看完代码之后不妨猜测一下输出结果:

class Dog{
    public void bark(){
        System.out.println("woof ");
    }
}
class Hound extends Dog{
    public void sniff(){
        System.out.println("sniff ");
    }

    public void bark(){
        System.out.println("bowl");
    }
}

public class OverridingTest{
    public static void main(String [] args){
        Dog dog = new Hound();
        dog.bark();
    }
}

输出结果:

bowl

上面的例子中,dog对象被定义为Dog类型。在编译期,编译器会检查Dog类中是否有可访问的bark()方法,只要其中包含bark()方法,那么就可以编译通过。在运行期,Hound对象被new出来,并赋值给dog变量,这时,JVM是明确的知道dog变量指向的其实是Hound对象的引用。所以,当dog调用bark()方法的时候,就会调用Hound类中定义的bark()方法。这就是所谓的动态多态性。

重写的条件

参数列表必须完全与被重写方法的相同;

返回类型必须完全与被重写方法的返回类型相同;

访问级别的限制性一定不能比被重写方法的强;

访问级别的限制性可以比被重写方法的弱;

重写方法一定不能抛出新的检查异常或比被重写的方法声明的检查异常更广泛的检查异常

重写的方法能够抛出更少或更有限的异常(也就是说,被重写的方法声明了异常,但重写的方法可以什么也不声明)

不能重写被标示为final的方法;

如果不能继承一个方法,则不能重写这个方法。

重载的例子

class Dog{
    public void bark(){
        System.out.println("woof ");
    }

    //overloading method
    public void bark(int num){
        for(int i=0; i<num; i++)
            System.out.println("woof ");
    }
}

上面的代码中,定义了两个bark方法,一个是没有参数的bark方法,另外一个是包含一个int类型参数的bark方法。在编译期,编译期可以根据方法签名(方法名和参数情况)情况确定哪个方法被调用。

重载的条件

被重载的方法必须改变参数列表;

被重载的方法可以改变返回类型;

被重载的方法可以改变访问修饰符;

被重载的方法可以声明新的或更广的检查异常;

方法能够在同一个类中或者在一个子类中被重载。

参考资料

Overriding vs. Overloading in Java

赞(6)
如未加特殊说明,此网站文章均为原创,转载必须注明出处。HollisChuang's Blog » 深入理解Java中的重写和重载
Hollis出品的全套Java面试宝典不来了解一下吗?

评论 5

  1. #1

    hollis大神哪一年毕业的啊,好厉害[/鼓掌]

    天涯海角9年前 (2016-03-21)回复
  2. #2

    个人理解重载只是语法或者编译时期存在的一种语法规则,因为重载的两个方法在编译时期根本就是两个不同的方法,因为确定唯一一个方法是根据方法名称,参数列表类型顺序来确定的。不知道我的理解对不对[emoji:d83dde44]

    每天要背十个单词词9年前 (2016-06-15)回复
    • 其实也就是语言特性吧,放有的语言上就可能不会认为这是两个不同的方法(函数),其实,在*.class中还会根据返回类型来判断是不是不同的方法,这就和重载的概念有些不一样了,可以了解一下。

      Feedmo8年前 (2016-09-10)回复
  3. #3

    访问级别的限制性一定不能比被重写方法的强;
    访问级别的限制性可以比被重写方法的弱;这块错了吧,根据EffectiveJava第13条,子类中的访问权限级别不允许低于超类的访问级别;比喻一下:父亲会的技能,儿子只能说更厉害,但不能说失去这个技能,从兼容性来说,也不用改低于父类的访问级别吧(一直学习您的博客文章,读了很多遍,受益匪浅。感谢)

    艾菲尔铁塔下的月光7年前 (2017-07-12)回复
    • 限制性强的意思就是访问控制级别高
      级别最低为 public,最高为 private;
      所以博主说的没有错

      Otokaze7年前 (2017-09-08)回复

HollisChuang's Blog

联系我关于我