继承的认识和学习 继承的概念继承是面向对象的一种概念它允许一个类子类基于另一个类父类来构建子类自动获取父类的属性和方法。同时可以扩展或修改这些属性和方法。 子类继承父类的类也成为派生类。 父类被继承的类也被称为基类或超类 继承主要解决的问题是共性的抽取实现代码复用。继承的语法使用extends关键字实现继承关系。子类通过extends继承父类的非私有成员字段和方法。1.修饰符class子类extends父类例如classParentClass{// 父类的属性和方法 }classChildClassextendsParentClass{// 子类可以添加新的属性和方法// 或重写父类的方法 }注意1.子类可以访问父类的公共public和受保护protected成员但私有private成员无法直接访问。2.子类继承父类之后必须要新添加自己特有的成员体现出与基类的不同否则就没有必要继承了父类成员的访问1.父类和子类成员变量不同名时直接继承即可//父类publicclassAnimal{//成员属性publicintage;publicStringname;//成员方法publicvoideat(){System.out.println(this.name正在吃饭...);}}//子类继承父类publicclassDogextendsAnimal{//子类的新成员属性publicStringlive;//子类的新成员方法publicvoidbark(){System.out.println(this.name正在汪汪叫...);}publicstaticvoidmain(String[]args){DogdognewDog();//给继承父类的属性赋值dog.age10;dog.name大黄;dog.eat();//子类的属性赋值dog.live中国;dog.bark();System.out.println(狗的年龄dog.age狗的名字dog.name狗的居住地dog.live);}}2.父类和子类的成员变量同名时publicclassAnimal{//成员属性publicintage5;publicStringname;//成员方法publicvoideat(){System.out.println(this.name正在吃饭...);}}publicclassDogextendsAnimal{publicintage10;//子类的新成员属性publicStringlive;//子类的新成员方法publicvoidbark(){System.out.println(this.name正在汪汪叫...);}publicstaticvoidmain(String[]args){DogdognewDog();System.out.println(狗的年龄dog.age);注意;在子类方法中 或者 通过子类对象访问成员时1.如果访问的成员变量子类中有优先访问自己的成员变量。2.如果访问的成员变量子类中无则访问父类继承下来的如果父类也没有定义则编译报错。3.如果访问的成员变量与父类中成员变量同名则优先访问自己的。4.成员变量访问遵循就近原则自己有优先自己的如果没有则向父类中找。子类中访问父类的成员方法成员方法名字不同publicclassAnimal{publicvoiduse2(){System.out.println(调用了Animal中的use2()...);}}publicclassCatextendsAnimal{//成员方法publicvoiduse1(){System.out.println(使用了Cat中的use1()...);}publicstaticvoidmain(String[]args){CatcatnewCat();cat.use1();cat.use2();}}总结成员方法没有同名时在子类方法中或者通过子类对象访问方法时则优先访问自己的自己没有时再到父类中找如果父类中也没有则报错。2. 成员方法名字相同publicclassAnimal{publicvoiduse1(){System.out.println(调用了Animal中的use2()...);}}publicclassCatextendsAnimal{//成员方法publicvoiduse1(){System.out.println(使用了Cat中的use1()...);}publicstaticvoidmain(String[]args){CatcatnewCat();cat.use1();}}成员方法名字相同1.当子类和父类的成员方法名字相同且参数列表也相同时会发生方法重写Override如果只是名字相同但参数列表不同则属于方法的重载Overload这两种情况的处理规则不同。2.子类定义了与父类方法名、参数列表、返回值类型或协变返回类型完全相同的方法称为方法重写。此时子类方法会覆盖父类方法调用时遵循 “运行时多态” 规则。super关键字在子类的方法中想要访问父类的成员时借助super 关键字即可。1.super可以访问⽗类的成员变量2.super可以访问⽗类的成员⽅法3.super还可以调⽤⽗类当中指定的构造⽅法接下来我们看⼀下注意1.只能在非静态方法中使用2.在子类方法中访问父类的成员变量和方法子类的构造方法子类构造方法在执行前必须先调用父类的构造方法。注意通过super 的形式可以调用父类的指定的构造方法super 的形式 只能出现在子类的构造方法中且必须在第一行publicclassAnimal{publicvoiduse1(){System.out.println(调用了Animal中的use2()...);}}publicclassCatextendsAnimal{publicvoiduse1(){System.out.println(使用了Cat中的use1()...);}publicvoidtest(){CatcatnewCat();cat.use1();super.use1();}publicstaticvoidmain(String[]args){CatcatnewCat();cat.test();}}总结;初始化顺序先父后子本质是 “成员构成决定初始化逻辑”子类对象的成员由两部分组成从父类继承的成员 子类新增的成员。“先有父再有子” 的逻辑决定了构造子类对象时必须先调用父类构造方法初始化继承的成员再执行子类构造方法初始化新增成员。即使子类构造中未写任何父类构造相关代码该顺序也不会改变。2. 父类有 “无参 / 默认构造” 时子类默认隐含super()调用若父类显式定义了无参构造如public Parent() {}或未定义任何构造编译器自动生成默认无参构造则子类构造方法的第一行会隐含super()无需手动写自动调用父类的无参构造。3. 父类只有 “有参构造” 时子类必须显式调用父类有参构造若父类仅定义了带参数的构造无无参构造编译器无法自动生成super()因找不到父类无参构造此时必须手动为子类定义构造方法在子类构造方法的第一行通过super(参数)显式调用父类的某一个有参构造否则编译报错。publicclassBase{inta;intb;//给Base构造方法Base(inta,intb){this.aa;this.bb;}}publicclassSubextendsBase{//必须给Sub构造方法且给Base中的成员初始化Sub(){super(5,10);}}super和this在Java中super和this都属于与关键字。1.this指代当前的对象其用于以下场景区分实例变量和局部变量当方法参数和成员变量同名时用this指定访问成员变量publicclasstest{privateinta;publicvoidset(inta){this.aa;// this.value 指实例变量value 指方法参数}}在构造方法中调用其他构造方法通过 this() 可以在一个构造方法中调用同一类的另一个构造方法但必须将其放在构造方法的第一行。publicclassExample{privateintx;privateinty;publicExample(intx,inty){this.xx;this.yy;}publicExample(){this(0,0);// 调用带参数的构造方法}}作为方法的返回值this 可以作为方法的返回值返回当前对象的引用常用于链式调用。classBuilder{privateStringinfo;publicBuildersetInfo(Stringinfo){this.infoinfo;returnthis;// 返回当前对象}}// 链式调用newBuilder().setInfo(test);2.super指代父类的对象主要运用的场景访问父类成员变量若子类与父类有同名变量使用super.variable可明确指定访问父类变量。classParent{StringvalueParent;}classChildextendsParent{StringvalueChild;voidshow(){System.out.println(super.value);// 输出 ParentSystem.out.println(value);// 输出 Child}}访问父类成员方法当子类重写父类方法时可通过super.method()调用父类被覆盖的方法避免递归调用。classParent{publicvoidshow(){System.out.println(父类方法);}}classChildextendsParent{Overridepublicvoidshow(){super.show();// 调用父类的show()System.out.println(子类方法);}}调用父类的构造方法用super(参数)在子类构造方法中调用父类的构造方法必须放在子类构造方法的第一行。classParent{Parent(Stringname){System.out.println(Parent: name);}}classChildextendsParent{Child(){super(Alice);// 必须显式调用父类有参构造器}}相同点1.都是Java的关键字2.只能在类的非静态方法中使用用来访问非静态成员方法和字段3.在构造方法中调用时必须是构造的第一条语句并且不能同时存在不同点1.this 是当前对象的引用当前对象即调用实例方法的对象super相当于是子类对象中从父类继承下来部分成员的引用。2.在非静态成员方法中this用来访问本类的方法和属性super用来访问父类继承下来的方法和属性3.在构造方法中this(…)用于调用本类的构造方法super(…)用于调用父类的构造方法两种调用不能同时在构造方法中出现4.构造方法中一定会存在super(…)的调用用户没有写编译器也会增加但是this(…)用户不写则没有publicclassAnimal{Animal(){System.out.println(Animal()...);}static{System.out.println(调用了Animal静态方法...);}{System.out.println(调用了Animal实例方法...);}}publicclassCatextendsAnimal{static{System.out.println(调用了Cat的静态方法...);}{System.out.println(调用了Cat的实例方法);}Cat(){System.out.println(调用了Cat()构造方法);}publicstaticvoidmain(String[]args){Catcat1newCat();System.out.println( 11);Catcat2newCat();}}执行结果调用了Animal静态方法…调用了Cat的静态方法…调用了Animal实例方法…Animal()…调用了Cat的实例方法调用了Cat()构造方法11调用了Animal实例方法…Animal()…调用了Cat的实例方法调用了Cat()构造方法注意静态代码块先执行并且只执行一次在类加载阶段执行当有对象创建时才会执行实例代码块实例代码块执行完成后最后构造方法执行