【潜意识Java】深入理解Java中的方法重写,理解重写的意义,知道其使用场景,以及重写的访问权限限制等的完整笔记详细总结。

简介: 本文详细介绍了Java中的方法重写概念、规则及应用场景。

 目录

一、方法重写是啥玩意儿

(一)定义和概念

(二)为啥要方法重写

二、方法重写的规则

(一)方法签名必须相同

(二)返回类型的要求

(三)访问权限的限制

(四)异常处理的规则

三、方法重写的示例代码

(一)简单的图形绘制示例

(二)动物发声示例

四、方法重写与方法重载的区别

(一)概念区别

(二)具体区别体现

五、方法重写在实际开发中的应用场景

(一)图形界面开发中的组件定制

(二)数据库访问层的优化

(三)游戏开发中的角色行为扩展


image.gif 编辑

宝子们,今天咱来好好唠唠 Java 中一个超重要的概念 —— 方法重写。这玩意儿在 Java 的面向对象编程里可是起着关键作用,能让我们的代码更加灵活、可扩展,就像是给汽车换上不同的轮胎,让它能适应各种路况。不过,要真正掌握方法重写,得从一些基础概念慢慢说起。

一、方法重写是啥玩意儿

(一)定义和概念

想象一下,你有一个类,就好比是一个汽车的蓝图。这个类里有一个方法,比如是 move 方法,代表汽车怎么移动。现在,你又有一个子类,这个子类就像是基于原来汽车蓝图改进的新车型。子类可以对从父类继承来的 move 方法进行重新定义,让它的移动方式更符合这个新车型的特点,这就是方法重写。

哈哈,是不是不怎么好理解?那用专业点的话说,方法重写就是在子类中定义一个与父类中具有相同方法签名(方法名、参数列表和返回类型都相同,不过返回类型在一些情况下可以是协变的,后面会讲到)的方法,这样当通过子类对象调用这个方法时,执行的就是子类中重写后的方法,而不是父类中的方法。

(二)为啥要方法重写

  • 增强功能:比如说,父类的 draw 方法只是简单地画一个图形的轮廓,而子类继承后,想要画一个填充了颜色的图形,就可以重写 draw 方法,在原来画轮廓的基础上添加填充颜色的代码,这样就增强了 draw 方法的功能,让子类的对象能展现出更丰富的行为。
  • 适应不同需求:以动物类为例,父类有一个 makeSound 方法,对于不同的子类,比如狗类和猫类,它们发出的声音是不一样的。狗是 “汪汪” 叫,猫是 “喵喵” 叫。通过在狗类和猫类中重写 makeSound 方法,就能让每个子类的对象发出符合自身特点的声音,从而适应了不同动物的行为需求。

二、方法重写的规则

(一)方法签名必须相同

  • 方法名一致:这很好理解,就像你要重写一个 openDoor 方法,在子类里也得叫 openDoor,不能改成别的名字,不然 Java 就不知道你是在重写父类的方法了。
  • 参数列表相同:参数的数量、类型和顺序都得一模一样。比如说父类的 calculate 方法接受两个 int 类型的参数,子类重写的 calculate 方法也得接受两个 int 类型的参数,不能多一个少一个,也不能把 int 换成其他类型,否则就不是方法重写,而是一个新的方法重载(这是另外一个概念,宝子们别搞混了哦)。

(二)返回类型的要求

  • 基本数据类型和无返回值:如果父类方法的返回类型是基本数据类型,比如 intdouble 等,或者是 void(无返回值),那么子类重写的方法返回类型必须和父类完全一致。例如,父类的 getCount 方法返回 int 类型,子类重写的 getCount 方法也必须返回 int 类型。
  • 引用数据类型的协变返回类型:如果父类方法的返回类型是一个引用数据类型,比如一个类或者接口,那么子类重写的方法返回类型可以是这个父类返回类型的子类。这就叫做协变返回类型。比如说,父类的 createShape 方法返回 Shape 类型,子类重写这个方法时,可以返回 Circle 类型(假设 CircleShape 的子类),这样做是合法的,而且更加灵活,能让子类返回更具体的类型,同时又保证了和父类方法的兼容性。

(三)访问权限的限制

子类重写方法的访问权限不能比父类中被重写的方法更严格。也就是说,如果父类的方法是 public 的,子类重写的方法可以是 public 或者 protected(但一般不建议把 public 改成 protected,除非有特殊的设计需求),但不能是 private 或者默认(包访问权限),因为这样会导致子类的方法无法在父类方法可访问的范围内被调用,就违背了方法重写的初衷。例如,父类的 display 方法是 public 的,子类重写的 display 方法可以是 public,但如果写成 private,那就错啦。

(四)异常处理的规则

子类重写方法抛出的异常类型不能比父类被重写方法抛出的异常类型更宽泛,只能是父类抛出异常类型的子类或者不抛出异常。这是为了保证在使用多态性时,通过父类引用调用方法时,不会出现意想不到的异常情况。比如说,父类的 processData 方法抛出 IOException,子类重写这个方法时,可以抛出 FileNotFoundException(因为 FileNotFoundExceptionIOException 的子类),或者不抛出任何异常,但不能抛出 Exception(因为 ExceptionIOException 更宽泛)。

image.gif 编辑

三、方法重写的示例代码

(一)简单的图形绘制示例

// 父类 Shape
class Shape {
    public void draw() {
        System.out.println("绘制一个基本图形");
    }
}
// 子类 Circle,继承自 Shape
class Circle extends Shape {
    @Override
    public void draw() {
        System.out.println("绘制一个圆形");
    }
}
// 子类 Rectangle,继承自 Shape
class Rectangle extends Shape {
    @Override
    public void draw() {
        System.out.println("绘制一个矩形");
    }
}
public class MethodOverrideExample1 {
    public static void main(String[] args) {
        Shape shape1 = new Circle();
        Shape shape2 = new Rectangle();
        shape1.draw();
        shape2.draw();
    }
}

image.gif

在这个例子中,Shape 类有一个 draw 方法,CircleRectangle 子类分别重写了这个方法,当通过父类 Shape 的引用指向子类对象并调用 draw 方法时,会执行子类中重写后的 draw 方法,分别输出 “绘制一个圆形” 和 “绘制一个矩形”,这就体现了方法重写的多态性效果。

(二)动物发声示例

// 父类 Animal
class Animal {
    public void makeSound() {
        System.out.println("动物发出声音");
    }
}
// 子类 Dog,继承自 Animal
class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("汪汪汪");
    }
}
// 子类 Cat,继承自 Animal
class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("喵喵喵");
    }
}
public class MethodOverrideExample2 {
    public static void main(String[] args) {
        Animal dog = new Dog();
        Animal cat = new Cat();
        dog.makeSound();
        cat.makeSound();
    }
}

image.gif

我解释一下哈,这里,Animal 类的 makeSound 方法在 DogCat 子类中被重写,通过父类引用调用 makeSound 方法时,分别输出狗和猫各自特有的叫声,展示了方法重写如何让不同子类的对象表现出独特的行为。

四、方法重写与方法重载的区别

(一)概念区别

  • 方法重写(Override):如前所述,是在子类中对父类的同名同参数列表方法进行重新定义,目的是改变方法的实现细节或者增强功能,以适应子类的特定需求,同时保持方法签名的一致性,从而实现多态性。
  • 方法重载(Overload):是在同一个类中定义多个方法名相同但参数列表不同(参数的数量、类型或者顺序不同)的方法。方法重载的目的是为了提供多种不同的操作方式,让调用者可以根据不同的参数情况选择合适的方法来执行。例如,一个 Calculator 类中可以有多个 add 方法,一个接受两个 int 参数,一个接受两个 double 参数,还有一个接受三个 int 参数,这样在进行加法运算时,可以根据传入的数据类型和数量选择合适的 add 方法。

这个往往有些人工作了,都不一定会的

(二)具体区别体现

  • 方法签名:方法重写要求方法签名完全相同(除了协变返回类型的情况),而方法重载要求方法名相同但参数列表不同,这是它们最明显的区别。
  • 返回类型:方法重写对于返回类型有严格的规则(如前面所讲的基本数据类型和引用数据类型的情况),而方法重载与返回类型无关,只要方法名和参数列表不同,返回类型可以相同也可以不同。
  • 调用方式:方法重写是通过父类引用指向子类对象,然后调用重写后的方法,实现多态性;而方法重载是在同一个类中,根据不同的参数情况,在编译时就确定调用哪个具体的重载方法。

下面通过代码示例来更清楚地展示它们的区别:

class MathOperations {
    // 方法重载示例
    public int add(int num1, int num2) {
        return num1 + num2;
    }
    public double add(double num1, double num2) {
        return num1 + num2;
    }
    public int add(int num1, int num2, int num3) {
        return num1 + num2 + num3;
    }
}
class Shape {
    public void draw() {
        System.out.println("绘制一个基本形状");
    }
}
class Circle extends Shape {
    @Override
    public void draw() {
        System.out.println("绘制一个圆形");
    }
}
public class OverrideVsOverload {
    public static void main(String[] args) {
        MathOperations math = new MathOperations();
        // 调用不同的重载方法
        int result1 = math.add(2, 3);
        double result2 = math.add(2.5, 3.5);
        int result3 = math.add(1, 2, 3);
        Shape shape = new Circle();
        // 调用重写后的方法
        shape.draw();
    }
}

image.gif

在这个例子中,MathOperations 类展示了方法重载,通过不同的参数列表实现了多个 add 方法;Circle 类重写了 Shape 类的 draw 方法,体现了方法重写。宝子们可以通过这个例子更清晰地看到它们的区别和各自的特点。

五、方法重写在实际开发中的应用场景

(一)图形界面开发中的组件定制

在图形用户界面(GUI)开发中,比如使用 JavaFX 或者 Swing 框架,有各种基本的组件类,如 ButtonLabel 等。我们经常需要创建自定义的组件来满足特定的界面设计需求。例如,我们可以继承 Button 类,重写它的 paint 方法,来改变按钮的外观样式,比如添加自定义的背景颜色、边框样式或者文字效果等。这样,通过方法重写,我们可以在不改变原有 Button 类基本功能的基础上,对其进行个性化的定制,使其更好地融入到我们设计的界面中。

(二)数据库访问层的优化

在企业级应用开发中,通常会有一个数据访问层(DAO)来与数据库进行交互。假设我们有一个通用的 BaseDAO 类,其中定义了一些基本的数据库操作方法,如 insertupdatedeleteselect 等。对于不同的实体类(如 UserProduct 等),它们在进行数据库操作时可能有一些特定的需求。例如,在插入 User 数据时,可能需要对密码进行加密处理;在查询 Product 数据时,可能需要根据不同的条件进行复杂的查询逻辑构建。这时候,我们可以创建 UserDAOProductDAO 等子类,继承自 BaseDAO,并在子类中重写相应的数据库操作方法,如 insertselect 方法,来实现针对不同实体类的特定数据库操作逻辑,从而优化数据库访问层的功能,使其更加高效和灵活。

(三)游戏开发中的角色行为扩展

在游戏开发中,经常会有各种角色类,它们可能都继承自一个公共的 Character 类。Character 类中定义了一些基本的行为方法,如 moveattackdefend 等。对于不同的角色,比如战士、法师和刺客等,它们的这些行为方式会有所不同。战士的 attack 方法可能是近身强力攻击,法师的 attack 方法可能是远程魔法攻击,刺客的 move 方法可能更加敏捷快速。通过在各个角色子类中重写这些方法,我们可以赋予每个角色独特的行为特点,让游戏更加丰富和有趣,同时也遵循了面向对象编程的开闭原则,即对扩展开放,对修改关闭,方便后续添加新的角色类型或者修改角色行为。

宝子们,方法重写在 Java 编程中是一个非常强大且实用的特性,它让我们的代码能够更好地适应各种变化和需求,实现更加灵活和优雅的设计。希望通过这篇文章,大家对方法重写有了更深入、更全面的理解,能够在今后的编程实践中熟练运用它,写出更加高质量的代码。如果在学习过程中遇到任何问题或者有不明白的地方,随时回来看看这篇文章,或者查阅更多的相关资料,不断练习和实践,相信你一定能掌握这个重要的概念!

image.gif 编辑


相关文章
|
24天前
|
Java 程序员 调度
Java 高级面试技巧:yield() 与 sleep() 方法的使用场景和区别
本文详细解析了 Java 中 `Thread` 类的 `yield()` 和 `sleep()` 方法,解释了它们的作用、区别及为什么是静态方法。`yield()` 让当前线程释放 CPU 时间片,给其他同等优先级线程运行机会,但不保证暂停;`sleep()` 则让线程进入休眠状态,指定时间后继续执行。两者都是静态方法,因为它们影响线程调度机制而非单一线程行为。这些知识点在面试中常被提及,掌握它们有助于更好地应对多线程编程问题。
55 9
|
26天前
|
NoSQL JavaScript 前端开发
Java访问MongoDB
Java访问MongoDB
41 21
|
30天前
|
存储 Java 开发者
【潜意识Java】深入详细理解分析Java中的toString()方法重写完整笔记总结,超级详细。
本文详细介绍了 Java 中 `toString()` 方法的重写技巧及其重要
50 10
【潜意识Java】深入详细理解分析Java中的toString()方法重写完整笔记总结,超级详细。
|
30天前
|
供应链 安全 Java
探索 Java 权限修饰符的奥秘
本文深入探讨了Java中的权限修饰符
47 12
|
30天前
|
算法 Java C++
【潜意识Java】蓝桥杯算法有关的动态规划求解背包问题
本文介绍了经典的0/1背包问题及其动态规划解法。
48 5
|
Java Windows 开发框架
Java初级笔记-第一章
第一章 Java概览 1.1 基本简介 Java是一种理想的面向对象的网络编程语言。 1991年,出现了Oak语言,旨在解决编程语言的选择和跨平台的问题。
1386 0
Java初级笔记-第二章
第二章 Java的基本数据类型、运算符及表达式 2.1 标识符 标识符是程序员对程序中的各个元素加以命名时使用的命名记号。
1221 0
|
存储 算法 Java
Java初级笔记-第三章
第三章 程序设计基础 3.1 流程图 3.1.1 什么是流程图: 流程图是通过箭头(流程线)相互连接的几何图形来表达程序运行的方法。
1423 0
Java初级笔记-第四章
第四章 类 4.1 类的概念 Java语言是一种纯面向对象的编程语言(OOP,你所有使用的内容,都是从类开始。
1284 0
Java初级笔记-第五章
第五章 面向对象的特点 5.1 继承 面向对象的重要特点之一就是继承。类的继承使得能够在已有的类的基础上构造新的类,新类除了具有被继承类的属性和方法外,还可以根据需要添加新的属性和方法。
1063 0