【JavaSE基础语法】07-继承与多态

发布时间:2026/7/2 7:46:35
【JavaSE基础语法】07-继承与多态 1. 继承面向对象思想提出了继承的概念专门用来进行共性抽取实现代码复用1.1继承的概念继承机制是面向对象程序设计使代码可以复用的最重要手段允许程序员在保持原有类特性的基础上进行扩展新增功能这样产生的类称为派生类。继承最大的作用就是共性抽取、实现代码复用以及是实现多态1.2 继承的语法在Java中如果要表示类之间的继承关系需要借助extends关键字修饰符class子类extends父类{//...}【注意】子类会将父类中的成员变量或成员方法继承到子类中1.3 父类成员访问1.3.1 子类访问父类中的成员变量子类和父类不存在同名成员变量publicclassBase{inta;intb;}publicclassDerivedextendsBase{intc;publicvoidmethod(){a10;//访问从父类中继承下来的ab20;//访问从父类中继承下来的bc30;//访问子类自己的c}}父类和子类成员变量同名publicclassBase{inta;intb;intc;}publicclassDerivedextendsBase{inta;// 与父类中成员 a 同名且类型相同charb;// 与父类中成员 b 同名但类型不同publicvoidmethod(){a100;//是子类自己的成员ab101;//是子类自己的成员bc102;//是父类的成员c// d 103; // 编译失败因为父类和子类都没有定义成员变量d}}在子类方法中 或者 通过子类对象访问成员时如果访问的成员变量子类中有优先访问自己的成员变量如果访问的成员变量子类中没有则访问父类继承下来的如果父类也没有则报错如果访问的成员变量与父类中成员变量同名则优先访问自己的1.3.2 子类中访问父类的成员方法成员方法不同名publicclassBase{publicvoidmethodA(){System.out.println(Base中的methodA());}}publicclassDerivedextendsBase{publicvoidmethodB(){System.out.println(Derived中的methodB()方法);}publicvoidmethodC(){methodB();//访问子类自己的 methodB()methodA();//访问父类继承的 methodA()// methodD(); //编译失败在整个继承体系中没有发现方法 methodD()}}【总结】成员方法没有同名时在子类方法或者通过子类对象访问方法时则优先访问自己的自己没有时再到父类中找如果父类也没有则报错成员方法名字相同publicclassBase{publicvoidmethodA(){System.out.println(Base中的methodA());}publicvoidmethodB(){System.out.println(Base中的methodB());}}publicclassDerivedextendsBase{publicvoidmethodA(inta){System.out.println(Derived中的method(int)方法);}publicvoidmethodB(){System.out.println(Derived中的methodB()方法);}publicvoidmethodC(){methodA();//没有传参访问父类中的 methodA()methodA(20);//传递 int 参数访问子类中的 methodA(int)methodB();//直接访问则永远访问到的都是子类中的 methodB()基类的无法访问到}}【说明】通过子类对象访问父类与子类中不同名方法时优先在子类中找找到则访问否则在父类中找找到则访问否则编译报错。通过派生类对象访问父类与子类同名方法时如果父类和子类同名方法的参数列表不同(重载)根据调用方法时传递的参数选择合适的方法访问如果没有则报错1.4 super关键字Java提供了super关键字主要作用是在子类方法中访问父类的成员publicclassBase{inta;intb;publicvoidmethodA(){System.out.println(Base中的methodA());}publicvoidmethodB(){System.out.println(Base中的methodB());}}publicclassDerivedextendsBase{inta;// 与父类中成员变量同名且类型相同charb;// 与父类中成员变量同名但类型不同// 与父类中 methodA() 构成重载publicvoidmethodA(inta){System.out.println(Derived中的method()方法);}// 与基类中 methodB() 构成重写即原型一致重写后序详细介绍publicvoidmethodB(){System.out.println(Derived中的methodB()方法);}publicvoidmethodC(){// 对于同名的成员变量直接访问时访问的都是子类的a100;// 等价于this.a 100;b101;// 等价于this.b 101;// 注意this 是当前对象的引用// 访问父类的成员变量时需要借助 super 关键字// super 可以在子类中访问父类的成员变量、成员方法或构造方法super.a200;super.b201;// 父类和子类中构成重载的方法直接可以通过参数列表区分访问父类还是子类方法methodA();//没有传参访问父类中的 methodA()methodA(20);//传递 int 参数访问子类中的 methodA(int)//如果在子类中要访问重写的基类方法则需要借助 super 关键字methodB();//直接访问则永远访问到的都是子类中的 methodB()基类的无法访问到super.methodB();//访问基类的 methodB()}}【注意事项】只能在非静态方法中使用1.5 子类构造方法子类对象中成员是有两部分组成的基类继承下来的以及子类新增加的部分。在构造子类对象的时候先要调用基类的构造方法将从基类继承下来的成员构造完整然后再调用子类自己的构造方法将子类自己新增的成员初始化完整。publicclassBase{publicBase(){System.out.println(Base());}}publicclassDerivedextendsBase{publicDerived(){//super(); //注意子类构造方法中默认会调用基类的无参构造方法super()//用户没有写时编译器会自动添加而且 super() 必须是子类构造方法中第一条语句//并且只能出现一次System.out.println(Derived());}}publicclassTest{publicstaticvoidmain(String[]args){DeriveddnewDerived();}}// 结果打印// Base()// Derived()【注意】若父类显式定义无参或者默认的构造方法在子类构造方法第一行默认有隐含的super()调用即调用基类构造方法。如果父类构造方法是带有参数的此时需要用户为子类显式定义构造方法并在子类构造方法中选择合适的父类构造方法调用否则编译失败。在子类构造方法中super(...)调用父类构造时必须是子类构造函数中第一条语句。super(...)只能在子类构造方法中出现一次并且不能和this(...)同时出现。1.6 super和this【相同点】只能在类的非静态方法中使用用来访问非静态成员方法和字段在构造方法中调用时必须是构造方法中的第一条语句并且不能同时存在【不同点】this是对当前对象的引用当前对象即调用实例方法的对象super相当于是子类对象从父类继承下来的部分成员的引用非静态成员方法中this用来访问本类的方法和属性super用来访问父类继承下来的方法和属性在构造方法中this(...)用于调用本类的构造方法super(...)用于调用父类的构造方法两种构造方法不能同时在构造方法中出现每个构造方法的第一条语句必须是this(...)或super(...)。如果没有显式写编译器会默认补上super()。如果写了this(...)则当前构造方法不会直接调用super(...)但最终会通过其他构造方法间接调用父类构造方法。1.7 执行顺序父类静态代码块优先子类静态代码块执行且是最早执行父类实例代码块和父类构造方法紧接着执行子类实例代码块和子类构造方法紧接着执行第二次实例化子类对象时父类和子类的静态代码块都将不会再执行1.8 继承方式【注意】Java 类不支持多继承即一个类只能extends一个父类但 Java 支持一个类实现多个接口。1.9 final关键字final关键字可以用来修饰变量、成员方法以及类修饰变量或字段表示常量即不能修改finalinta10;a20;//编译出错修饰类表示此类不能被继承我们平时使用的String字符串类就是用final修饰的不能被继承finalpublicclassAnimal{...}publicclassBirdextendsAnimal{...}//编译出错修饰方法表示该方法不能被重写1.10 继承与组合和继承类似组合也是一种表达类之间关系的方式也是能够达到代码重用的效果。组合并没有涉及到特殊的语法(诸如extends这样的关键字)仅仅是将一个类的实例作为另外一个类的字段。// 轮胎类classTire{// ...}// 发动机类classEngine{// ...}// 车载系统类classVehicleSystem{// ...}classCar{privateTiretire;//可以复用轮胎中的属性和方法privateEngineengine;//可以复用发动机中的属性和方法privateVehicleSystemvs;//可以复用车载系统中的属性和方法// ...}// 奔驰是汽车classBenzextendsCar{//将汽车中包含的轮胎、发动机、车载系统全部继承下来}组合和继承都可以实现代码的复用一般建议能使用组合尽量使用组合2. 多态概念多态就是去完成某个行为当不同的对象去完成时就会产生出不同的状态2.1 多态的实现条件必须在继承体系下子类必须要对父类中方法进行重写通过父类的引用调用重写的方法多态的体现在代码运行时当传递不同类对象时会调用对应类中的方法publicclassAnimal{Stringname;intage;publicAnimal(Stringname,intage){this.namename;this.ageage;}publicvoideat(){System.out.println(name eat);}}publicclassCatextendsAnimal{publicCat(Stringname,intage){super(name,age);}Overridepublicvoideat(){System.out.println(name eat fish);}}publicclassDogextendsAnimal{publicDog(Stringname,intage){super(name,age);}Overridepublicvoideat(){System.out.println(name eat bone);}}publicclassTestAnimal{publicstaticvoideat(Animala){a.eat();}publicstaticvoidmain(String[]args){CatcatnewCat(哈基米,2);DogdognewDog(大黄,1);eat(cat);eat(dog);}}//输出结果//哈基米 eat fish//大黄 eat bone2.2 重写重写override也称为覆盖。重写是子类对父类中非静态、非private、非final、非构造方法 等方法的实现过程进行重新编写返回值和形参都不能改变。即外壳不变核心重写。重写的好处在于子类可以根据需要定义特定于自己的行为。也就是说子类能够根据需要实现父类的方法。【方法重写的规则】子类在重写父类的方法时一般必须与父类方法原型一致:返回值类型方法名(参数列表)要完全一致被重写的方法返回值类型可以不同但是必须是具有父子关系的访问权限不能比父类中被重写的方法的访问权限更低static方法不能被重写只能被隐藏private方法对子类不可见不能被重写final方法不能被重写构造方法不能被继承因此也不能被重写重写的方法可以使用Override注解来显式指定.有了这个注解能帮我们进行一些合法性校验【重写和重载的区别】区别点重写override重载overload参数列表一定不能修改必须修改返回类型一定不能修改除非可以构成父子类关系可以修改访问限定符一定不能做更严格的限制可以降低限制可以修改【重写的设计原则】对于已经投入使用的类尽量不要进行修改。最好的方法是重新定义一个新的类类重复利用其中共性的内容并添加或者改动新的内容2.3 向上转型和向下转型2.3.1 向上转型就是创建一个子类对象将其当成父类对象来使用父类对象 对象名new子类类型();【使用场景】publicclassTestAnimal{// 2. 方法传参形参为父类型引用可以接收任意子类的对象publicstaticvoideatFood(Animala){a.eat();}// 3. 作返回值返回任意子类对象publicstaticAnimalbuyAnimal(Stringvar){if(狗.equals(var)){returnnewDog(狗狗,1);}elseif(猫.equals(var)){returnnewCat(猫猫,1);}else{returnnull;}}publicstaticvoidmain(String[]args){AnimalcatnewCat(元宝,2);// 1. 直接赋值子类对象赋值给父类对象DogdognewDog(小七,1);eatFood(cat);eatFood(dog);AnimalanimalbuyAnimal(狗);animal.eat();animalbuyAnimal(猫);animal.eat();}}【优点】让代码实现更灵活【缺点】不能调用到子类特有的方法2.3.2 向下转型将一个子类对象经过向上转型之后当成父类方法使用再无法调用子类的方法但有时候可能需要调用子类特有的方法此时将父类引用再还原为子类对象即可即向下转型向下转型用的比较少而且不安全万一转型失败运行时就会抛异常。Java中为了提高向下转型的安全性引入了instanceof如果该表达式为true则可以安全转移publicclassTestAnimal{publicstaticvoidmain(String[]args){CatcatnewCat(元宝,2);DogdognewDog(小七,1);// 向上转型Animalanimalcat;animal.eat();animaldog;animal.eat();if(animalinstanceofCat){cat(Cat)animal;cat.mew();}if(animalinstanceofDog){dog(Dog)animal;dog.bark();}}}2.4 多态的优缺点【优点】能够降低代码的“圈复杂度”避免大量使用if-else可扩展性强【缺点】通过父类引用只能访问父类中声明的成员不能直接访问子类特有方法如果需要访问子类特有方法可能需要向下转型存在类型转换风险。