JAVASE 小白学习笔记(7)初进面向对象-继承(继承特点,this与super关键字,方法重写以及final关键字)

1.继承的引入

在生活中,有形形色色的继承,最常见的继承是一个家族财产的继承关系,儿子可以继承父亲的财产。在Java中也存在继承关系,Java中的继承是子类可以继承父类的成员(成员变量与成员方法)。
Java中继承关系的语法为:
用extends关键字来进行继承,让类与类之间产生继承关系。

下面我们先用生活中一个简单的例子来引入Java中的继承关系:
我们知道动物里面有很多类别,例如猫,狗之类的,都有一些共性的东西。例如吃饭,睡觉等。那么我们就可以将这些共性的东西向上抽取到Animal这个类中,在子类中直接就会继承,可以大量的减少代码量,实现代码的实用性与维护性。

//父类:
public class Anmial {
    
    
    //将子类共有的东西向上抽取到父类,以实现代码的复用性与维护性
    public String name;
    public int age;
    public void eat(){
    
    
        System.out.println("吃饭");
    }
    public void sleep(){
    
    
        System.out.println("睡觉");
    }
}
//子类:
public class Cat extends  Anmial {
    
    
    //子类中可以保留自己特有的方法
    public void catchMouse(){
    
    
        System.out.println("猫抓老鼠");
    }
}
public class Dog extends Anmial {
    
    
    public void lookDoor(){
    
    
        System.out.println("小狗看门");
    }
}
//测试类:
public class MyTest {
    
    
    public static void main(String[] args) {
    
    
        Cat cat = new Cat();
        cat.name="胖橘";
        cat.age=3;
        System.out.println(cat.name);
        System.out.println(cat.age);
        cat.eat();
        cat.sleep();
        cat.catchMouse();
        System.out.println("================");
        Dog dog = new Dog();
        dog.name="小强";
        dog.age=5;
        System.out.println(dog.name);
        System.out.println(dog.age);
        dog.eat();
        dog.sleep();
        dog.lookDoor();
    }
}


运行的结果为:
胖橘
3
吃饭
睡觉
猫抓老鼠
================
小强
5
吃饭
睡觉
小狗看门

  • 继承的利弊分析
继承的好处 继承的弊端
提高了代码的复用性与维护性 让类与类之间产生了依赖的关系,增加了耦合性
继承是多态的前提,有了继承才能谈及多态 当依赖关系太过于紧密时,会违背软件的设计原则:高内聚,低耦合
让类与类之间有了继承关系 耦合性过高时,不利于软件后期的维护和扩展

2.继承的特点

  • Java中继承语法:Java中只支持单继承,不支持多继承。可以支持多层继承
  • Java中子类只能继承父类的非私有成员。私有成员,子类不能继承。
  • 构造方法不参与继承
  • 静态方法可以继承
//Object 是我们Java继承体系当中的顶层父类
//所有的类都是直接或间接继承自他。
public class MyTest2 extends Object{
    
    
    public static void main(String[] args) {
    
    
        /*Java中继承的语法特点
        1.Java中只支持单继承
        一个子类只能有一个父类,
        一个父类是可以有多个子类。
        不支持多继承。可以支持多层继承。
        2.子类只能继承父类非私有的成员。私有的成员,子类不能继承。
        3.构造方法,不参与继承。构造方法,在你初始化子类对象时,
            会调用父类构造来完成父类数据的初始化。
        4.静态方法也是可以继承的。*/

        D d = new D();
        d.hehe();

        D.hehe();


    }
}

class A extends Object{
    
    
//子类不能继承父类中的私有变量
   private int a=10;
    public void a(){
    
    

    }
}

class B extends A{
    
    
    int b=100;
    //子类不能继承父类的私有方法
    private void b(){
    
    }
}

class C extends B{
    
    
    int c=70;
    public void c(){
    
    }
    public static void hehe(){
    
    

    }
}
class D extends C{
    
    

}
}

  • 当我们创建子类对象时,会先调用父类的构造方法的原因:当我们去创建子类对象时,子类会继承父类的一些数据,会先完成父类数据的初始化,然后初始化自己的数据
public class MyTest {
    
    
    public static void main(String[] args) {
    
    
        /*当我们创建子类对象时,会先调用父类的构造方法,为什么?
        当我们去创建子类对象时,子类要继承父类的一些数据甚至还要去使用,
        那如果子类的数据没有完成初始化,子类能继承吗?肯定不行。
        所以当我们创建子类对象时,应该先完成父类数据的初始化,
        然后在初始自己的数据。
         */
        /*创建子类成员变量时,会先调用父类的构造方法,
        然后在调用子类构造方法
         */
        Zi zi = new Zi();

    }
}

class Fu extends Object{
    
    
    int a=20;
   public Fu(){
    
    
       super();
       System.out.println("父类的构造方法执行了");
   }
}

class Zi extends Fu{
    
    
    public Zi(){
    
    
        super(); //调用父类的空参构造
        System.out.println("子类的构造方法执行了");
    }
}

3.this 、super关键字

super关键字
super:表示父类的空间标识,可以简单理解为父类的一个引用,使用super可以调用父类的数据
super.变量名:调用父类的变量
super.方法名():调用父类的方法
super():调用父类的空参构造
super(有参):调用父类的有参构造
this关键字
this:表示本类的一个引用,谁调用这个方法,方法中的this就代表谁
this.变量名:调用本类的变量
this.方法名():调用本类的方法
this():调用本类的空参构造
this(有参):调用本类的有参构造
public class MyTest {
    
    
    public static void main(String[] args) {
    
    
        ZZ zz = new ZZ();
        zz.ziHeHe(140);
    }
}
class FF{
    
    
    int num=20;
    private int bb=250;
    public int cc=1405;

    public void fuShow(){
    
    
        System.out.println(num+"父类的方法");
    }
    public int  getBB(){
    
    
        return this.bb;
    }
}
class ZZ extends FF{
    
    
    int z=100;
    int num=800;

    public void ziHeHe(int num) {
    
    
        /*
          变量访问的就近原则。
        * 当我们在方法中访问一个变量的时候,先从局部范围找,
          找到就使用,如果没找到,去本类的成员范围找,找到就使用,
        * 如果没找到,会去父类的成员范围找,找到就使用
        * 局部变量和成员变量以及父类的成员变量重名问题,
          可以使用  this super 来区分
        * */

        System.out.println(num);//140
        System.out.println(this.num);//800
        System.out.println(super.num);//20
        System.out.println(cc);
    }
    public void ziShow(){
    
    
        System.out.println(this.z);
        System.out.println(this.num);
        System.out.println(super.num);
        this.fuShow();
        super.fuShow();
       // System.out.println(super.bb); 报错
        int bb = this.getBB();
        int bb1 = super.getBB();
        System.out.println(bb);
        System.out.println(bb1);

    }


}

4.方法重写

在继承关系中,当子类与父类存在一模一样的方法,可以进行方法重写。

  • 方法重写:子类中出现与父类一模一样的方法(方法名,参数列表以及返回值的类型),也称为方法重写或者方法覆盖。
  • 子类会覆盖父类的方法,实际运行时,运行的是子类重写过的方法
  • 方法重写的机制:一个父类会有多个子类,父类里面抽取的是所有子类共性的功能,但每个子类对于共性功能的具体实现,存在差异。
  • 子类方法重写的目的:就是对父类功能实现不满意,想要根据自己的需求,进行重写与扩展

4.1 方法重写(功能重写)

//父类
public class Animal {
    
    
	//对于子类中共性功能进行提取
    public void eat() {
    
    
        System.out.println("吃饭");
    }

    public void sleep() {
    
    
        System.out.println("睡觉");
    }
}
//子类
public class Cat extends Animal{
    
    
    public void catchMouse(){
    
    
        System.out.println("抓老鼠");
    }

    public void eat(){
    
    
        System.out.println("猫爱吃小鱼干");
    }

    public void sleep(){
    
    
        System.out.println("猫喜欢白天睡觉");
    }

}
public class Dog extends Animal{
    
    
    public void lookDoor(){
    
    
        System.out.println("狗看门");
    }

    public void eat(){
    
    
        System.out.println("狗吃骨头");
    }
}
//测试类
public class MyTest {
    
    
    public static void main(String[] args) {
    
    
        Cat cat = new Cat();
        cat.eat();
        cat.sleep();
        System.out.println("=====================");
        Dog dog = new Dog();
        dog.sleep();
        dog.eat();
    }
}


输出的结果为:

猫爱吃小鱼干
猫喜欢白天睡觉
=====================
睡觉
狗吃骨头

4.2 方法重写(功能扩展)

  • 对于某部分代码满意,还想扩展,也可以通过方法重写来实现
//父类:手机类
public class Phone {
    
    
    public Phone() {
    
    
        System.out.println("构造方法执行了");
    }

    public void call() {
    
    
        System.out.println("打电话 ");
    }

    public void send() {
    
    
        System.out.println("发短信");
    }
}
//子类:Iphone手机
public class Iphone extends Phone{
    
    
    public void palyGame(){
    
    
        System.out.println("玩游戏");
    }

    @Override //注解   
    // @Override 这个注解的作用,是用来检测此方法是不是重写父类的方法
    public void call() {
    
    
        super.call(); //沿袭父类的功能
        System.out.println("高清视频通话");
    }
}
//测试类:
public class MyTest {
    
    
    public static void main(String[] args) {
    
    
        Iphone iphone = new Iphone();
        iphone.call();
        iphone.send();
        iphone.palyGame();
    }
}

输出的结果为:
打电话
高清视频电话
发短信

4.2 方法重写的注意事项

方法重写的注意事项
父类的私有方法,子类不能进行重写(因为父类的私有方法,子类都不能继承,就更不能进行重写
父类的构造方法不能重写(构造方法不参与继承)
静态方法不参与重写
子类在重写父类方法时,方法的权限修饰符,不能比父类的低,可以与父类的权限修饰符保持一致(权限:public>protected>缺省>私有)
public class MyTest {
    
    
    public static void main(String[] args) {
    
    
        //方法重写时,需要注意的事项。
        //1.父类私有的方法,子类不能重写,私有方法,子类不能继承
        //2.父类构造方法,不能重写,构造方法没有继承一说。
        //3.子类在重写父类方法时,方法的权限修饰符,
        // 不能比父类的低可以跟父类的一样,或者比父类的高
        //public>protected>缺省的>private
        //4.静态方法,不参与重写

        Father.haha();

        Son son = new Son();
        son.haha();
        Son.haha();

    }

}

class Father{
    
    
    private void show(){
    
    

    }

    protected void hehe(){
    
    

    }
    public static void haha(){
    
    
        System.out.println("父类的静态方法");
    }

}
class Son extends Father{
    
    
    @Override
    protected void hehe() {
    
    

    }

    //@Override  静态方法不参与重写
    public static void haha() {
    
    
        System.out.println("子类的静态方法");
    }

}

5.final关键字

  • final关键字是最终的意思,可以修饰类,变量,成员方法。
final修饰特点
修饰类: 被修饰类不能被继承
修饰方法: 被修饰的方法不能被重写
修饰变量: 被修饰的变量不能被重新赋值,因为这个量其实是一个常量
public class MyTest {
    
    
    //公共的静态常量
 public static final double AA=3.14; //自定义常量
    public static void main(String[] args) {
    
    
        //final 最终的,可以修饰成员变量,局部变量,形参,也可以修饰方法,也可以修类
        //修饰变量,此变量为一个常量,既然为常量,常量的值就不能再次被改变。
        //自定义常量,常量名一般建议大写
        final int NUM=100;
              //NUM=200; //重新赋值,报错,常量不能再次赋值
        System.out.println(NUM);
        double aa = MyTest.AA;
        System.out.println(aa);

        BB bb = new BB();
        System.out.println(bb);
           bb=new BB();
        System.out.println(bb);

        System.out.println("============================");
       final BB bb1 = new BB();
        //final修饰的是基本类型,指的是值不能再次被改变。
        //final修饰的是引用数据类型,指的是这个地址值,不能再次被改变
        //final修饰方法,此方法,不能被子类重写,但是可以让子类继承去用
        CC cc = new CC();
        cc.show();
        //final 修饰类,此类不能被继承
      
    }
}

class BB{
    
    
   public final void show(){
    
    
       System.out.println("父类的final修饰的方法,子类不能重写,子类可以继承");
   }
}

class CC extends BB{
    
    
 /*   @Override
    public void show() {

    }*/
}
//final修饰类,此类不能被继承
 final class EE{
    
    

}
/*
class FF extends EE{

}
*/

猜你喜欢

转载自blog.csdn.net/qq_41537102/article/details/110225610