千锋教育-做有情怀、有良心、有品质的职业教育机构

当前位置:首页  >  关于学院  >  技术干货  >  Java技术干货  >  正文

从零开始学Java之方法重写与方法重载的区别

来源:千锋教育
作者:qyf
关键词: 方法 父类
2023-03-20
分享

  一. 方法重写

  在面向对象中,实现多态的必备条件是继承、重写和向上转型,现在我们已经学习了什么是继承。接下来我们再来学习什么是方法重写,这是我们能够实现多态的前提。

  概念

  如果我们在子类中,创建了一个与父类中名称、返回值类型、参数列表都完全相同的方法,只是方法体的功能实现不同,这种方式被称为方法重写(override),或者叫方法覆盖。当父类中的方法无法满足子类的需求,或者子类需要有特殊功能时,就可以进行方法重写。

  基本要求

  我们在进行方法重写时,需要遵循以下几点要求:

  ● 父类的成员方法只能被它的子类重写,即不能继承一个方法,就不能重写这个方法;

  ● 被final修饰的方法不能被重写;

  ● 被static修饰的方法不能被重写,但可以再次声明;

  ● 构造方法不能被重写;

  ● 子类和父类在同一个包中时,子类可以重写父类中除了被private和final修饰的其他所有方法;

  ● 子类和父类不在同一个包中时,子类只能重写父类被public和protected修饰的非final方法;

  ● 重写的方法建议使用@Override注解来标识。

  注意事项

  另外我们在进行方法重写时,还要注意以下几点:

  ● 方法签名要相同:重写的方法和被重写的方法,在方法名、参数上都要相同;

  ● 返回值类型一致:JDK 1.5之前重写方法的返回值类型必须一样,但之后的Java版本放宽了限制,返回值类型必须小于或等于父类方法的返回值类型;

  ● 访问修饰符要更宽泛:子类重写父类的方法时,子类方法中的访问修饰符不能比父类中的更严格(public>protected>default>private)。比如父类方法的修饰符是protected,则子类的同名方法其修饰符可以是protected或public,但不能是默认的或private;

  ● 声明的异常类型要一致:重写的方法一定不能抛出新的检査异常,或者比被重写方法声明更宽泛的检査型异常。例如,父类的方法声明了IOException,重写该方法时就不能抛出Exception,只能拋出IOException或其子类异常。但可以抛出非检査异常。

  代码实现

  接下来壹哥就通过一个案例来给大家讲解方法的重写该怎么实现。

  定义父类

  我们先定义一个Father父类,要注意父类中有哪些方法不能被重写。

  public class Father {

  // 父类中的成员变量--变量隐藏

  String name="老子";

  //构造方法不能被重写,因为构造方法不能被继承!

  public Father() {

  System.out.println("爹的构造方法");

  }

  // 吃

  public void eat() {

  System.out.println("爹吃馒头");

  }

  // 喝

  public void drink() {

  System.out.println("爹喝水");

  }

  // 玩

  //私有方法不能被重写

  // private void play() {

  // System.out.println("爹玩火");

  // }

  //静态方法不能被重写,但可以在子类中声明一个同样的静态方法。复制代码

  // public static void play() {

  // System.out.println("爹玩火");

  // }

  //final方法不能被重写public final void play() {

  System.out.println("爹玩火");

  }

  }

  4.2 定义子类

  定义一个Son子类继承父类,有了继承才会有重写!

  public class Son extends Father{

  //构造方法不能被重写,因为构造方法不能被继承!//@Override//public Father() {}

  // 吃/**

  * 方法重写时可以带有@Ovriride关键词,当重写的方法签名不一致时,可以有编译错误的提示。

  * 否则方法签名不一致时不会有错误提示,会被当做一个新的方法来处理。

  */@Overridepublic void eat() {

  //如果子类的功能,是在父类的基础之上进行的额外扩展增加,

  //我们可以使用super关键字调用父类的同名方法,然后再进行自己的额外扩展!

  //如果子类的实现和父类完全不一样,可以不调用super!

  super.eat();

  //方法重写时,子类可以对父类的同名方法进行扩展实现,方法体的内容可以和父类中的实现不一样

  System.out.println("儿子吃肉");

  }

  // 喝@Overridepublic void drink() {

  //如果子类的实现和父类完全不一样,可以不调用super!

  System.out.println("儿子喝酒");

  }

  /**

  * 父类私有的、static、final等方法无法被重写

  *///@Override//public void play() {}

  //static静态的父类方法不能被重写,但可以在子类中再重新编写一个静态的同名方法。//public static void play() {}

  //变量隐藏--调用父类和子类中的同名成员变量public void sayHello() {

  // 如果子类的实现和父类完全不一样,可以不调用super!

  System.out.println("父亲的名字=" + super.name);

  System.out.println("儿子的名字=" + name);

  }

  public static void main(String[] args) {

  Son son = new Son();

  son.sayHello();

  }

  }

  我们在进行方法重写时,要注意以下几点:

  ● 方法重写时可以带有@Ovriride关键词。当重写的方法签名不一致时,会有编译错误的提示,否则方法签名不一致时不会有错误提示,会被当做一个新的方法来处理。

  ● 当子类对象调用重写的方法时,默认执行的是子类的方法,而不是父类中被重写的方法。如果我们想要调用父类中被重写的方法,则可以使用“super.方法名”的形式。

  ● 如果子类的功能是在父类的基础之上进行的额外扩展,我们可以使用super关键字调用父类的同名方法,然后再进行自己的额外扩展!

  ● 如果子类的实现和父类完全不一样,可以不调用super!

  ● 方法重写时,子类可以对父类的同名方法进行扩展实现,方法体的内容可以和父类中的实现不一样。

  @Override注解

  在上面的代码中,我们用到了一个新的关键字@Override。在Java中,@Override是一个注解,关于注解的更多内容,壹哥会在后面的文章中进行专门讲解,现在我们先知道注解这个概念就行。

  @Override是一个用来修饰被重新的方法的注解,只能用在被重新的方法上,不能用在其它的地方。该注解可以强制子类必须重写父类的方法或者接口中的方法,主要是告诉编译器检查重写的方法是否和父类中定义的一致。如果重写的方法签名不一致,会提示编译错误。如果方法签名不一致,则不会有错误提示,会被当做一个新的方法来处理。通过这样的机制,就可以避免程序员出现一些低级的错误。

  变量隐藏

  概念

  如果子类中定义了一个成员变量,而该变量的名称与父类中的成员变量相同,数据类型不一定完全一致,我们就把这称为变量隐藏。也就是说,子类的成员变量,对从父类继承过来的成员变量进行了重新定义,出现了子类变量对父类变量的隐藏。所以子类执行自己定义的方法时,操作的成员变量默认是自己定义的变量,而不是父类中的同名变量。如果我们非要操作隐藏的成员变量,可以使用super关键字进行调用。

  接下来我们通过一个案例来给大家演示变量隐藏的使用。

  案例实现

  父类中定义一个成员变量name,如下图所示:

图片 1

  子类中也定义一个相同的成员变量name,如下图所示:

图片 2

  如果我们在Son类中直接使用name,默认使用的是Son自己的变量;如果我们想使用Father类中的name变量,则可以通过“super.属性”的形式进行。执行结果如下图所示:

图片 3

  方法隐藏

  在子类继承父类时,既然存在变量隐藏的现象,同理也存在方法隐藏的现象。

  6.1 概念

  我们知道,方法的重写是子类覆盖父类的对象方法,而方法隐藏则是子类覆盖父类的静态方法(类方法)。在java中的静态方法能被子类继承吗?答案是肯定的,但若子类中有与父类中同名同参的方法,则父类的方法将被隐藏。

  6.2 案例实现

  我们先定义一个Father父类,里面有个静态方法eat。

  /**

  ·

  @author 一一哥Sun

  ·

  ·

  QQ:2312119590

  ·

  ·

  CSDN、掘金、知乎找我哦

  ·

  ·

  ·

  定义父类

  */

  public class Father {

  ·

  // 吃---静态方法

  public static void eat() {

  System.out.println("爹吃馒头");

  }

  ·

  }

  然后再定义一个Son子类,里面也有一个静态方法eat。我们知道,静态方法是可以被继承的,所以如果Son子类中没有定义自己的eat()方法,默认可以使用Father父类中的eat()方法。但如果我们在子类中也定义了一个eat()方法,子类的同名静态方法就会隐藏父类中的eat()方法,这就是方法隐藏。

  /**

  ·

  @author 一一哥Sun

  ·

  ·

  QQ:2312119590

  ·

  ·

  CSDN、掘金、知乎找我哦

  ·

  ·

  ·

  子类继承父类

  */

  public class Son extends Father {

  ·

  // 吃---静态方法

  //如果子类中没有定义该方法,则子类可以继承使用父类的eat()方法

  public static void eat() {

  //子类覆盖父类中的同名静态方法(类)

  System.out.println("儿子吃肉");

  }

  ·

  public static void main(String[] args) {

  //调用子类自己的静态方法

  eat();

  //调用父类的静态方法

  Father.eat();

  }

  ·

  }

  执行结果如下图所示:

图片 4

  小结

  通过本案例,我们可以得出以下结论:

  1. 子类可以继承父类中的静态方法;

  2. 子类无法重写父类中的静态方法,但可以重载;

  3. 若子类中定义了与父类中同样的静态方法,则父类的同名方法会被子类隐藏。

  二. 重写与重载的区别

  在Java中既有方法重写(Override),也有方法重载(Overload),对于初学者来说很容易搞混。所以有不少面试官,在招聘初级程序员时,就很喜欢问我们方法重写与方法重载的区别。

  其实方法重写Override和方法重载Overload的最大不同,在于方法签名的不同。如果同一个类中的多个方法签名不同,就是方法重载Overload,重载出的方法是一个新方法。如果父子类之间的多个方法签名相同,且返回值也相同,就是方法重写Override。

  当然,如果你想把关于重写和重载的区别说得更详细,可以参考以下章节。

  4. 重载的特点

  ● 方法重载要求方法同名不同参(参数类型、个数、顺序);

  ● 重载的方法与返回值、访问修饰符无关;

  ● 重载的方法发生在同一个类中,是在一个类中创建多个同名的方法。

  5. 重写的特点

  ● 重写的方法发生在父子类中,需要有继承关系;

  ● 父类的成员方法只能被它的子类重写,即不能继承一个方法,就不能重写这个方法;

  ● 被final修饰的方法不能被重写;

  ● 被static修饰的方法不能被重写,但可以再次声明;

  ● 构造方法不能被重写;

  ● 子类和父类在同一个包中时,子类可以重写父类中除了被private和final修饰的其他所有方法;

  ● 子类和父类不在同一个包中时,子类只能重写父类被public和protected修饰的非final方法;

  ● 方法重写时可以使用@Override注解;

  ● 方法签名要相同;

  ● 返回值类型一致;

  ● 访问修饰符要更宽泛;

  ● 声明的异常类型要一致。

声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。

相关推荐

  • springcloud和dubbo的区别是什么? SpringCloud和Dubbo是两个在分布式系统开发中常用的框架,它们有以下几个主要区别:1.生态系统和发展历程:-Dubbo是由阿里巴巴集团开发并开源的,主要在中国的互联网企业中广泛使用,并且有
  • dubbo是什么?有哪些特性?-小王 Dubbo是一个开源的高性能RPC(远程过程调用)框架,由阿里巴巴集团开发并开源。它提供了分布式服务治理的解决方案,旨在简化大规模分布式系统中服务之间的通信和调用。Dubbo的设计目标是提供高性能、透
  • java面试之消息队列mq的实现原理 消息队列(MessageQueue)是一种在应用程序之间传递消息的通信模式。它提供了一种异步的、解耦的方式来实现不同系统、模块或组件之间的通信。消息队列的实现原理可以简要概括如下:1.**消息发布(P
  • java hash 加密字符串,使用 MessageDigest 类 在Java中,可以使用MessageDigest类来进行哈希加密(散列算法)。下面是使用MessageDigest类进行字符串哈希加密的示例:importjava.security.MessageDi
  • java object添加属性怎么实现? 在Java中,一个对象的属性通常是在类的定义中声明的,并通过类的构造函数或方法来进行初始化和设置。但是,如果你想为一个已有的对象动态添加属性,Java并没有直接支持这种操作。然而,你可以使用其他方式来
  • stringbuilder字符串 StringBuilder是一个用于构建和操作字符串的类,通常用于需要频繁拼接和修改字符串的场景,特别是在循环中。在许多编程语言中都有类似于StringBuilder的概念,下面是一个Java语言中使