Java的继承

继承

继承的概念

继承是面向对象程序设计使代码可以复用(重复的使用)的最重要的手段,它允许程序员在保持原有类特 性的基础上进行扩展,增加新功能,这样产生新的类,称子类(派生类),继承呈现了面向对象程序设计的层次结构, 体现了由简单到复杂的认知过程
继承主要解决的问题是:共性的抽取,实现代码复用
例如:狗和猫都是动物,那么我们就可以将共性的内容进行抽取,然后采用继承的思想来达到共用
在这里插入图片描述

在这里插入图片描述

继承的语法

在Java中如果要表示类之间的继承关系,需要借助extends关键字
例如:

修饰符 class 子类 extends 父类 {
// ...
}

我们写一个例子来说明一下父类和子类
例如:
在这里插入图片描述
结果:

在这里插入图片描述

子类访问父类成员

访问父类成员有二种情况

  • 子类和父类不存在同名成员变量
    这种情况下可以直接正常的访问
    例如:
    父类
class Animal{
 String name;
    int age;
}

子类(Dog) 继承 父类(Animalclass Dog extends Animal{
    int yog = 1;            子类自己的成员变量
    void bark(){
        yog = 66;           访问子类自己的成员
        name = "旺财";      这是子类访问继承父类的成员
        System.out.println(name + "在玩耍");
    }
}
  • 子类和父类成员变量同名
    这种情况也分二种:
    1 与父类中成员同名,且类型相同
    2 与父类中成员同名,但类型不相同
    父类
class Animal{
    int a = 1;
    int b = 2;
    int c = 3;
}

class Dog{
   int a;           1 与父类中成员同名,且类型相同
   char b;          2 与父类中成员同名,但类型不相同
   public void Add(){
        a = 16;     
        b = 86;
        c = 99;
    }
    这种情况下是优先访问子类自己的成员,没有在从父类找
}
结果: 16 86 99
  • 如果访问的成员变量里,子类里有的优先访问自己成员变量,没有在到父类中找
    如果都没有编译器就会报错,成员变量访问遵循就近原则,自己有优先自己的,如果没有则向父类中找

super关键字

super关键字:如果子类和父类中存在相同名称的成员,通过super .就可以在子类中访问父类的成员
super关键字有三种用法:
访问父类普通成员变量、访问父类普通成员方法、调用父类的构造方法

  • 访问父类普通成员变量
    例如:在子类和父类成员变量名字类型都相同的情况下
//父类
class A {
    String name = “大黑”;
    int age;   
}
//子类
class pen extends A{
    String name = “小白”;
    double age;
    public void house(){
        System.out.println(super.name + "正在看家");
    }

 super 是获取到子类对象中从基类继承下来的部分

结果:
在这里插入图片描述

  • 子类访问父类的成员方法
    父类和子类中构成重载的方法,直接可以通过参数列表区分清访问父类还是子类方法
    在这里插入图片描述
  • super 只能在非静态的成员方法里使用
  • 访问父类的方法或者成员,必须在子类的方法里
  • 对于父类的private成员变量,子类会继承该成员变量,但是不可以访问
  • java不支持多继承,即一个类只能继承一个父类

子类构造方法

如果子类里有构造方法,那么需要先调用父类构造方法,然后执行子类的构造方法
子类构造方法有二种:
父类构造方法无参数
父类构造方法有指定参数

  • 父类构造方法无参数
    无参数的情况下,在你没有提供构造方法时,编译器会默认提供一个无参数的构造方法
class A {
    public String name;
    public int age;
    //父类无参数的构造方法 如果没有写编译器会默认提供一个
    public A() {
        System.out.println("父类 A() 构造方法");
    }
}
class B extends A{
    int a = 0;
     //子类无参数的构造方法 如果没有写编译器会默认提供一个
        public B(){
            System.out.println("子类 B() 构造方法");     
        }
    }

结果:

在这里插入图片描述

  • 父类构造方法有指定参数
    如果父类构造方法是带有参数的,此时需要自己给子类定义构造方法,并且子类的参数必须和父类的相同
    并且子类构造方法中必须先给父类构造方法初始化,否则编译失败在这里插入图片描述

总结:

  • 如果父类构造方法是无参数的,编译器会默认给子类提供一个无参数构造方法
  • 如果父类构造方法是有参数的,那么子类的构造方法必须自己定义,并且参数必须和父类的一样
  • 子类对象中成员是有两部分组成的,父类继承下来的以及子类新增加的部分
    在程序执行过程中,会先在构造子类对象时候 ,先要调用父类的构造方法,将从父类继承下来的成员构造初始化,然后再调用子类自己的构造方法,将子类自己新增加的成员初始化完整
  • 子类构造方法在先初始化父类的构造方法时,使用的 super( ) 必须是在子类构造的第一行
  • super只能在子类构造方法中出现一次,并且不能和this同时出现

super 和 this 的不同之处

super this都可以在成员方法中用来访问:成员变量调用其他的成员函数
并且都要作为构造方法的第一条语句,那么它们之间的区别呢

  • 相同之处
    superthis 都是Java 的关键字,并且只能在类的非静态方法中使用,用来访问非静态成员方法字段
    在构造方法中调用时,必须是构造方法中的第一条语句,但是它们不能同时存在
  • 不同之处
  1. this是哪个对象调用它,引用的就是那个对象
    super是只引用子类继承父类的成员变量或者方法
  2. . 在非静态成员方法中
    this用来访问本类的方法和属性
    super用来访问父类继承下来的方法和属性
  3. 在构造方法中:
    this(...)用于调用本类构造方法
    super(...)用于调用父类构造方法,并且两种调用不能同时在构造方法中出现
  4. 构造方法中一定会存在super(...)的调用,用户没有写编译器也会增加,但是this(...)用户不写则没有

子类和父类在代码块的执行顺序

之前在没有继承的情况下代码块的执行顺序:静态代码块、实例代码块、构造方法
静态代码块是只执行一次的
实例代码块和构造方法是对象调用几次就使用几次

如果在父类和子类还有构造方法里写静态代码和实例代码,执行的顺序还会一样吗?
例如:

class A {
    public String name;
    public int age;

    public A(String name,int age) {
        System.out.println("父类A() 构造方法");
    }

    {
        System.out.println("父类实例代码块");
    }

    static{
        System.out.println("父类静态代码块");
    }
}
class B extends A{
        public B(String name,int age){
            super(name,age);
            System.out.println("子类 B() 构造方法");
        }
    {
        System.out.println("子类实例代码块");
    }

    static{
        System.out.println("子类静态代码块");
    }
}

public class Test {
    public static void main(String[] args) {
        B a  = new B("小明",20);
        System.out.println("===========================");
        B b = new B("小红",18);
    }

结果:

在这里插入图片描述
总结:

  1. 父类静态代码块优先于子类静态代码块执行,且是最早执行
  2. 父类实例代码块和父类构造方法紧接着执行
  3. 子类的实例代码块和子类构造方法紧接着再执行
  4. 第二次引用实例化子类对象时,父类和子类的静态代码块都将不会再执行

protected 关键字

protected 作用:限定了类或者类中成员能否在类外或者其他包中被访问

protected 在同一包中相同的类使用:

在这里插入图片描述

protected 在同一包中不同类使用:

在这里插入图片描述

protected 在不同包中的子类中使用:

在这里插入图片描述

继承的方式

Java 继承的方式有三种:
例如:
在这里插入图片描述

  • Java 不支持一个类继承二个类
  • 一般继承不要超过三层

final 关键字

final 可以用类修饰变量、成员方法、类

  • 使用 final 修饰变量:
final int a = 10;
变量在被 final 修饰后变成了常量,就不能在被修改了
a = 20; 编译出错
  • 使用 final 修饰方法:
之后在补充
  • 使用 final 修饰类:

final 修饰后被称为 密封类
被修饰后这个类就不能在被继承

final public class Animal {
...
}

Java 的组合

组合 和 继承 类似,也是一种表达类之间关系的方式, 也是能够达到代码复用的效果
组合是将一个类或多个类作为成员变量(属性)来使用

例如:
学生和老师是学校的一部分,可以组合到学校的类中

class Student{ // 学生
}
class Teacher{ //老师
}
class School{ // 学校
     public Student[] stu;
     public Teacher[] t;
}

总结

  • 继承

继承可以使面向对象的代码进行复用,可以使一个类继承另一个类的成员变量(属性)和方法
继承可以分二种:父类子类
继承父类的成员变量(属性)和方法的被称为 子类(派生类)
被继承的类叫 父类(基类、超类)
继承是通过 extends 关键字进行

  • 子类访问父类成员

子类访问父类的成员或者方法时必须在方法里进行
如果子类和父类成员变量同名的情况下,是优先访问子类的成员,没有在到父类中找
如果子类和父类成员变量同名且类型不同的情况下,是通过类型来区分

  • super关键字

super 作用:从子类中找继承父类的成员变量和方法,使用方法:super . 变量名
如果子类和父类成员变量同名的情况下,在使用super优先访问父类的成员
如果父类和子类中构成重载的方法,直接可以通过参数列表区分清访问父类还是子类方法
super只能在非静态的成员方法里使用,而且必须在子类的方法里使用

  • 子类构造方法

对象是通过构造方法进行实例化的,编译器会默认提供一个
如果父类的构造方法是无参数的,编译器会默认在子类提供一个构造方法
如果父类构造方法是有参数的,那么子类的构造方式必须自己写,而且子类构造的参数必须和父类的一样
在初始化时,必须先在子类的方法里初始化父类,在初始化子类自己的 在初始化父类构造方法时,
使用的 super 必须是在方法的第一行,并且不能和this同时出现

  • superthis 的区别

super 是用来找子类继承父类的成员变量和方法的
this 是谁调用它,引用的对象就是谁

  • 子类和父类在代码块的执行顺序

在子类和父类里定义静态代码块、实例代码块、构造方法时
执行的顺序:父类和子类静态代码父类的实例代码块和构造方法子类的实例代码块和构造方法
静态代码块优先执行的,如果有多个静态代码块,是按照从上到下按顺序执行
静态代码块是只执行一次的,其他是按照顺序进行执行,先调用那个执行那个

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值