Java面向对象:继承与多态

张开发
2026/4/21 5:52:18 15 分钟阅读

分享文章

Java面向对象:继承与多态
Java面向对象继承与多态1. 引入为什么需要继承1.1 代码重复的问题假设你要定义两个类学生和老师。classStudent{privateStringname;privateintage;privateStringstudentId;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.namename;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.ageage;}}classTeacher{privateStringname;privateintage;privateStringteacherId;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.namename;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.ageage;}}问题name和age相关的代码写了两遍如果以后要加一个字段两个类都要改。1.2 继承的解决方案把公共的部分抽取到父类中// 父类classPerson{privateStringname;privateintage;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.namename;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.ageage;}}// 子类继承父类classStudentextendsPerson{privateStringstudentId;// 自己独有的属性}classTeacherextendsPerson{privateStringteacherId;// 自己独有的属性}子类自动拥有了父类的属性和方法代码复用维护也方便。2. 继承的基本概念2.1 继承的格式class子类extends父类{// 子类自己的成员}2.2 继承的特点特点说明单继承Java只支持单继承一个子类只能有一个父类多层继承可以有多层如A→B→CC继承B的B继承A的所有类都继承Object如果没写extends默认继承Object类2.3 继承的优点和缺点优点代码复用减少重复便于维护改父类子类自动生效为多态打下基础缺点父子类耦合度高父类改了子类可能受影响破坏了封装子类可以访问父类的protected成员3. 继承中成员变量的访问3.1 不同名变量子类和父类变量名不同直接访问就行classFather{intmoney100;}classSonextendsFather{intcar1;voidshow(){System.out.println(money);// 100继承来的System.out.println(car);// 1自己的}}3.2 同名变量就近原则子类和父类变量名相同时优先用子类的classFather{intscore80;}classSonextendsFather{intscore95;voidshow(){intscore100;System.out.println(score);// 100局部变量System.out.println(this.score);// 95子类成员System.out.println(super.score);// 80父类成员}}3.3 super关键字super用来访问父类的成员用法说明super.成员变量访问父类的成员变量super.成员方法访问父类的成员方法super()调用父类的构造方法4. 继承中成员方法的访问4.1 方法重写Override子类可以对父类的方法进行重写提供自己的实现classAnimal{publicvoidspeak(){System.out.println(动物叫);}}classCatextendsAnimal{Overridepublicvoidspeak(){System.out.println(喵喵喵);}}4.2 重写的条件条件要求方法名必须相同参数列表必须相同返回值类型必须相同或者是其子类访问权限不能低于父类父类public子类不能private异常不能抛出比父类更大的异常4.3 Override注解推荐在重写的方法上加Override注解让编译器帮忙检查是否真的重写了提高代码可读性4.4 重写 vs 重载维度重写Override重载Overload发生位置父子类之间同一个类中方法名相同相同参数列表必须相同必须不同返回值相同或其子类无关注解Override无5. 继承中构造方法5.1 父子类构造方法的执行顺序子类构造方法默认第一行会调用父类的无参构造classFather{publicFather(){System.out.println(父类构造方法);}}classSonextendsFather{publicSon(){super();// 默认就有可以省略System.out.println(子类构造方法);}}// 创建对象SonsnewSon();// 输出// 父类构造方法// 子类构造方法5.2 父类没有无参构造怎么办如果父类只写了有参构造没有无参构造子类必须手动用super(参数)调用classFather{privateStringname;publicFather(Stringname){// 只有有参构造this.namename;}}classSonextendsFather{publicSon(Stringname){super(name);// 必须手动调用父类的有参构造}}5.3 super()的规则规则说明必须写在第一行super()必须是构造方法的第一条语句和this()互斥一个构造方法不能同时调用super()和this()不写默认有如果不写编译器会自动加super()6. 多态6.1 什么是多态同一种行为不同对象表现出不同形态。比如“吃”这个行为猫吃鱼狗吃肉人吃饭6.2 多态的条件条件说明继承有父子类关系重写子类重写了父类的方法父类引用指向子类对象Father f new Son();6.3 多态的代码体现classAnimal{publicvoideat(){System.out.println(动物吃东西);}}classCatextendsAnimal{Overridepublicvoideat(){System.out.println(猫吃鱼);}}classDogextendsAnimal{Overridepublicvoideat(){System.out.println(狗吃肉);}}publicclassTest{publicstaticvoidmain(String[]args){// 多态父类引用指向子类对象Animala1newCat();Animala2newDog();a1.eat();// 猫吃鱼a2.eat();// 狗吃肉}}6.4 多态的成员访问特点成员类型访问特点成员变量编译看左边运行看左边用父类的成员方法编译看左边运行看右边用子类的静态方法编译看左边运行看左边不算重写classFather{intnum10;publicvoidshow(){System.out.println(Father show);}publicstaticvoidtest(){System.out.println(Father static);}}classSonextendsFather{intnum20;Overridepublicvoidshow(){System.out.println(Son show);}publicstaticvoidtest(){System.out.println(Son static);}}// 使用FatherfnewSon();System.out.println(f.num);// 10父类的变量f.show();// Son show子类的方法f.test();// Father static静态方法看左边7. 多态的优缺点7.1 优点解耦方法参数写成父类类型可以接收任何子类对象// 不用多态每种动物都要写一个方法publicvoidfeedCat(Catcat){cat.eat();}publicvoidfeedDog(Dogdog){dog.eat();}publicvoidfeedPig(Pigpig){pig.eat();}// 用多态一个方法搞定所有publicvoidfeed(Animalanimal){animal.eat();}扩展性新增动物类不需要修改已有代码。7.2 缺点不能直接调用子类特有方法AnimalanewCat();a.eat();// 父类有可以a.catchMouse();// 父类没有不能调用解决方法向下转型if(ainstanceofCat){Catc(Cat)a;c.catchMouse();// 转成Cat后可以调用}8. 向上转型和向下转型8.1 向上转型自动CatcatnewCat();Animalanimalcat;// 向上转型自动完成特点父类引用指向子类对象但只能调用父类已有的方法。8.2 向下转型强制AnimalanimalnewCat();Catcat(Cat)animal;// 向下转型需要强制转换8.3 instanceof关键字向下转型前建议先用instanceof判断类型AnimalanimalnewCat();if(animalinstanceofCat){Catcat(Cat)animal;cat.catchMouse();}elseif(animalinstanceofDog){Dogdog(Dog)animal;dog.watchHouse();}Java 16 新写法if(animalinstanceofCatcat){cat.catchMouse();// 自动转换直接用}9. 综合总结9.1 继承总结维度要点格式class 子类 extends 父类单继承一个子类只能有一个父类成员变量就近原则用super访问父类成员方法可以重写用Override注解构造方法先调用父类构造再调子类9.2 多态总结维度要点条件继承 重写 父类引用指向子类对象变量编译运行都看左边父类方法编译看左边运行看右边子类重写的静态编译运行都看左边转型向上自动向下强制建议先instanceof9.3 对比表格对比项继承多态核心作用代码复用灵活扩展关键词extends父类引用指向子类对象方法调用调用哪个看对象类型编译看左运行看右典型场景抽取公共代码方法参数写成父类类型10. 易错点总结把重写写成重载参数列表不同导致不是重写而是新方法子类构造方法忘记调用super父类没有无参构造时必须手动调用this和super混淆this访问当前类super访问父类向下转型不判断类型可能导致ClassCastException

更多文章