首页 > 其他分享 >方法重写和多态

方法重写和多态

时间:2025-01-12 16:11:11浏览次数:1  
标签:调用 静态方法 重写 多态 子类 父类 方法

3.多态 :父类的引用指向子类的对象

方法的重写:子类对父类方法的重写

定义:

  • 方法重写是子类重新定义继承自父类的方法,并提供自己版本的实现。子类方法名、返回值类型和参数列表必须与父类的被重写方法完全一致

特点:

  • 方法名相同:子类方法必须与父类方法的名称相同。
  • 参数列表相同:子类方法的参数列表必须与父类方法相同(包括参数个数、类型和顺序)。
  • 返回类型相同:子类方法的返回类型必须与父类方法相同,Java 5 引入了协变返回类型,即子类方法可以返回父类方法返回类型的子类(子类方法返回类型可以是父类方法返回类型的子类)。
  • 访问权限子类方法的访问权限可以与父类方法相同或更宽松不能更严格例如,父类方法是 public,子类方法也必须是 publicprotected,不能是 private
  • 异常处理子类方法抛出的异常类型可以与父类方法抛出的异常类型相同或更少但不能更多

要注意的点:

  • 子类不能重写父类的 privatefinalstatic 方法
    • private:父类的方法被标记为 private 时,它对子类是不可见的,因此子类无法重写该方法。
    • final:父类的方法被标记为 final 时,表示该方法不允许被重写。
    • static:静态方法是与类绑定的,不能被实例化的对象调用,因此无法重写静态方法(但可以隐藏父类的静态方法)。
  • @Override 注解:虽然不是必须的,但推荐在子类重写父类方法时使用 @Override 注解,这样可以帮助我们检查是否正确地重写了方法。如果子类方法与父类方法不一致,编译器会报错。

方法的重载:同一类中方法的扩充

  • 方法重载是在同一个类中,方法名相同但参数列表不同(参数类型、参数个数或参数顺序不同)。重载方法根据调用时传入的参数类型或个数来确定调用哪个版本的方法。

特点:

  • 方法名相同:重载的方法必须有相同的方法名。
  • 参数列表不同:参数的数量、类型、顺序必须不同。
  • 返回类型可以不同:方法的返回类型可以与其他重载方法不同,但这不是重载的条件,重载是根据参数来判断的,返回类型并不影响方法的重载。
  • 与返回类型无关:仅仅改变返回类型不足以构成方法的重载。

父类A

package com.oop.demo05;

public class A {
 //定义父类非静态方法
 public void run(){
     System.out.println("A===>run");
 }

 //定义静态方法
 public static void test(){
     System.out.println("A===>test");
 }
 public void test2(){
     System.out.println("A===>test2");
 }
}

子类 B

package com.oop.demo05;

public class B extends A {
 //定义子类非静态方法
 @Override //alt+insert 快速插入重写
 public void run() {
     System.out.println("B===>run");
 }

 public int add(int a, int b) {
     return a + b;
 }

 //定义子类静态方法    静态的好像不支持重写
 public static void test(){
     System.out.println("B===>test");
 }

}
package com.oop.demo05;
//方法重写 子类改写父类的方法
//多态
public class Application {
 public static void main(String[] args) {
     B  b1 = new B();
     b1.run();//是子类B类型 指向的是子类B实例  调用的是子类中的 run方法
     b1.test();//静态的要关注对象的类型(左边) B类的就执行B中的静态方法

     A b2 = new B();//父类引用指向子类对象   b2是父类A 类型  指向的是子类B的实例
     b2.run();//尽管这里b2 是父类A中的类型 指向的却是B中的实例,如果run只在父类A中定义 就执行A类中的run方法,但是子类B将run方法重写了,执行就得执行子类中得方法
     // 注意如果没有在子类重写方法 调用B类单独的方法(在子类未重写得方法)是会报错的 但是可以强转子类的类型就可以调用了 看第15行
     b2.test();//调用静态方法 看左边 用的是父类A 中的静态方法

     //b2.add(3,2) 方法不重写 调用子类单独的方法会报错!
     //((B) b2).add(3,  把父类类型强转到子类类型就可以使用子类方法了
     System.out.println(((B)b2).add(3, 2)); //把父类类型强转到子类类型就可以使用子类方法了

     b2.test2();//单纯继承 且子类中没有重写  直接使用父类中test2方法

     A a1 = new A();
     a1.run();

 }
}

输出结果

B===>run
B===>test
B===>run
A===>test
5
A===>test2
A===>run

总结:

1. 方法重写(Override)

  • 子类可以 重写 父类的方法,改变父类方法的行为。

  • 实例方法重写

    如果子类重写了父类的方法,

    调用的是子类重写后的方法

    例如:

    public class B extends A {
        @Override
        public void run() {
            System.out.println("B===>run");
        }
    }
    

    在 B类中重写了 run()方法,那么通过 B类的实例调用 run() 方法时,会执行 B 类中的实现。

2. 多态(Polymorphism)

  • 多态允许

    父类类型的引用指向子类的对象

    即:

    A b2 = new B();  // 父类引用指向子类对象
    
  • 在这种情况下,虽然 b2 是 A 类型的引用,但它指向的是 B类型的对象。调用实例方法时,实际执行的是 B 类中的重写方法因为在运行时,会根据实际对象的类型来决定调用哪个方法。即:

    b2.run();  // 调用的是 B 中重写的 run 方法
    
  • 静态方法与多态的关系

    静态方法 :不支持重写

    但会根据引用类型来调用静态方法。因此,静态方法调用时,看左边的引用类型

    例如:

    b2.test();  // 调用的是 A 中的静态方法
    

3. 访问子类独有的方法

  • 如果子类有在父类中没有定义的方法(如

    add()
    

    那么通过父类的引用

    不能直接调用子类的独有方法

    例如:

    b2.add(3, 2);  // 编译时错误,因为 A 中没有 add 方法
    
  • 要调用子类独有的方法,可以

    强制类型转换

    将父类类型转换为子类类型:

    System.out.println(((B)b2).add(3, 2));  // 强转为 B 类型,调用 B 中的 add 方法
    

4. 静态方法调用

  • 静态方法是 类级别的方法,与对象的实例无关。

  • 在多态中,静态方法的调用

    不会

    随对象类型的变化而变化,而是根据引用类型来决定调用哪个静态方法。因此,

    b2.test()
    

    仍然调用 A类的静态方法因为 b2是 A类型的引用尽管它指向的是 B 类型的实例

    b2.test();  // 调用的是 A 中的静态方法
    

5. 继承父类的方法

如果子类没有重写父类的方法,那么就会调用父类的方法。例如:

b2.test2();  // 调用 A 中的 test2 方法,因为 B 中没有重写

6. 总结

  • 实例方法:调用时,根据实际对象的类型决定调用父类还是子类的方法。

    A a =new B(); 是A类型 B实例

    B b =new B();是B类型 B实例

    所以a用A类中的方法或者B中重写好的方法注意若未重写,要么重写要么强制类型转换成子类,b用B类中的方法,子类一般不能强制转换成父类

  • 静态方法:调用时,根据引用类型决定调用父类还是子类的方法,静态方法不支持重写。

  • 多态:通过父类引用指向子类对象,调用实例方法时会调用子类重写的方法,但静态方法调用时看左边的引用类型。

  • 强制类型转换:可以通过强制转换,调用子类特有的方法。

    1. 关于 a(父类引用指向子类对象)

    • aA 类型的引用,但它指向的是 B 类型的对象。
    • 实例方法:调用时会首先检查子类是否重写了父类的方法。如果子类重写了,则调用子类的版本;如果没有重写,则调用父类的方法。
    • 静态方法:静态方法的调用决定于引用类型(即 A)。即使 a 指向的是 B 类型的对象,静态方法也会调用 A 中定义的静态方法。
    • 强制类型转换:如果你想调用子类中未在父类中定义的方法,必须将父类引用强制转换为子类类型。例如,((B) a).add(3, 2)
    • 补充a 不能直接调用 B 中独有的(未重写的方法),即使 a 指向的是 B 类的对象。只有当你进行强制类型转换时,才能调用子类特有的方法。

    总结

    • a 可以使用 A 中的方法,也可以使用 B 中重写的实例方法。
    • 若没有重写子类的方法,你可以通过强制类型转换调用子类特有的方法。
    • a 不能直接使用 B 类中独有的(未重写的)方法,除非通过强制类型转换。

    2. 关于 b(子类引用指向子类对象)

    • bB 类型的引用,指向的是 B 类型的对象。
    • b 可以直接调用 B 中的方法,包括子类特有的方法。
    • 静态方法:调用时,静态方法还是会根据引用类型(B)来调用 B 类中的静态方法。
    • b 不需要强制类型转换,因为它本来就是 B 类型。

    3. 子类不能强制转换为父类

    • 子类对象可以赋值给父类引用,但父类引用不能直接赋给子类类型的变量,因为编译时无法确定它的具体类型。

    • 错误的示例

      B b = new A();  // 这是错误的,不能将父类对象赋给子类引用
      

    总结归纳:

    • 父类引用指向子类对象
      1. 调用实例方法时,会调用子类重写的方法(如果子类没有重写,调用父类的方法)。
      2. 调用静态方法时,调用父类的静态方法,因为静态方法是编译时绑定的。
      3. 如果父类没有定义的方法,且子类有,必须强制转换为子类类型才能调用。
      4. 不能直接调用子类中独有的方法,如果想使用,必须强制转换。
    • 子类引用指向子类对象
      1. 可以直接调用子类重写的方法。
      2. 可以调用子类独有的非静态方法。
      3. 不需要强制类型转换。
    • 强制类型转换
      1. 如果父类引用指向子类对象,想调用子类特有的方法,可以通过强制类型转换来实现。

代码的核心行为:

  1. b2.run() 输出 "B===>run",因为 B 类重写了 A 类的 run() 方法。
  2. b2.test() 输出 "A===>test",因为静态方法是由引用类型决定的,b2A 类型的引用。
  3. ((B)b2).add(3, 2) 强制转换后调用 B 类中独有的 add() 方法。
  4. b2.test2() 输出 "A===>test2",因为 B 类没有重写 test2() 方法。
b2.test2();  // 调用 A 中的 test2 方法,因为 B 中没有重写

标签:调用,静态方法,重写,多态,子类,父类,方法
From: https://www.cnblogs.com/panghuhu-space/p/18667013

相关文章

  • leetcode2585 获得分数的方法数
    考试中有n种类型的题目,给定整数target和二维数组types,其中types[i]=[count[i],marks[i]],表示第i种类型的题目有count[i]道,每道分值为marks[i]。求在考试中恰好得到target分的方法数,答案对1E9+7取模。注意,同类型题目无法区分。1<=target<=1000;1<=n<=50;1<=count[i],marks[i]<=5......
  • 宇航用VIRTEX5系列FPGA的动态刷新方法及实现
    SRAM型FPGA在宇航领域有广泛的应用,为解决FPGA在空间环境中的单粒子翻转问题,增强设计的可靠性,本文介绍一种低成本的抗辐照解决方案。该方案从外置高可靠存储器中读取配置数据,通过定时刷新结合三模冗余的方式消除单粒子影响,提高系统的鲁棒性。    1.总体设计    ......
  • Java 方法
    在Java编程语言中,方法(Method)是执行某些特定功能的代码块。方法是Java程序结构的基本组成部分之一,它使得代码更加模块化,具有良好的可复用性和可维护性。通过方法,可以将复杂的任务拆分成更小的子任务,使得程序更加清晰和易于管理。1方法的结构方法一般包含以下几个部分:......
  • 服务器组件端口开通方法及注意事项
    开通服务器组件端口是确保服务正常运行的关键步骤之一。无论是操作系统层面还是通过管理工具如宝塔面板,都需要遵循一定的流程来确保端口能够正确开放,并且不会带来安全隐患。以下是详细的开通方法和注意事项:操作系统层面开通端口:Windows服务器:打开“高级安全Windows防火墙”......
  • 宝塔面板默认用户名和密码的查找与重置方法
    对于初次安装或重装系统后的宝塔面板,默认的用户名和密码确实是一个常见的困惑点。以下是几种有效的解决方法,帮助您快速恢复对宝塔面板的访问权限:查看官方文档:宝塔面板官方提供了详细的安装指南和常见问题解答。其中包含了如何获取默认登录信息的内容。您可以参考(网址)中的说明......
  • 四个方法,恢复word文档内容
    在日常办公和学习中,MicrosoftWord文档作为我们存储和编辑文字内容的主要工具,其重要性不言而喻。然而,文档丢失、损坏或被误删的情况时有发生,这无疑给我们的工作和学习带来了极大的困扰。幸运的是,有多种方法可以帮助我们恢复丢失或损坏的Word文档。本文将详细介绍几种有效的Word......
  • 基于Java的世界时区自动计算及时间生成方法
    在全球化日益加强的今天,处理世界各地不同的时间和时区变得尤为重要。Java提供了丰富的工具来帮助我们处理时区、时间和日期相关的操作。本文将介绍如何基于Java自动计算不同世界时区的时间,并生成相应的时间。一、时区和时间计算概述时区(TimeZone):表示不同地区的时间规......
  • 写一个判断数据类型的方法
    在前端开发中,JavaScript是一种常用的编程语言,你可以使用typeof操作符来判断一个变量的数据类型。下面是一个简单的函数,它接受一个参数并返回该参数的数据类型:functiongetType(value){returntypeofvalue;}你可以这样使用这个函数:console.log(getType(123));......
  • 写一个获取当前url查询字符串中的参数的方法
    在前端开发中,你可以使用JavaScript的URLSearchParams接口来获取URL查询字符串中的参数。以下是一个简单的方法,它接受一个URL作为参数,并返回一个包含所有查询参数的对象:functiongetQueryParams(url){consturlObj=newURL(url);constparams=newURLSearchParams(urlO......
  • 写一个把字符串大小写切换的方法
    在前端开发中,可以使用JavaScript来实现一个方法,该方法可以将字符串中的大小写进行切换。以下是一个示例实现:functionswitchCase(str){letresult='';for(leti=0;i<str.length;i++){constchar=str[i];if(char===char.toUpperCase()){/......