Java 中的继承介绍和使用

发布于 2021-07-02 13:10:24 字数 4172 浏览 1565 评论 0

一、继承的概述

继承的好处

1、提高了代码的复用性

2、让类与类之间产生了关系,给第三个特征多态提供了前提。

多重继承问题

java 中支持单继承,不直接支持多继承,但对C++中多继承机制进行了改良。

单继承:一个子类只能有一个直接父类。

多继承:一个子类可以有多个直接父类(java 中不允许,进行改良 -> 多重继承) 不直接支持是因为多个父类中有相同的成员时,会产生调用不确定性。

二、继承的特点

在子父类中,成员的特点体现

成员变量

当本类的成员变量和局部变量同名时,用this区分 当子父类中的成员变量同名时,用super区分父类

this代表一个本类对象的引用 super代表一个父类空间

成员函数

当子父类中出现成员函数一模一样(函数名、返回值、参数个数、参数类型)的情况,会运行子类的函数。这种现象,称为覆盖操作。

函数两个特性:

1、重载。同一个类中 2、覆盖。子类中。覆盖也称为重写,覆写。

注意:子类方法覆盖父类方法时,子类全县必须要大于等于父类的权限。静态只能覆盖静态,或被静态覆盖。

构造函数

子父类的构造函数特点:

在子类构造对象时候,发现,访问子类构造函数时,父类也就运行了。 原因是:在子类构造函数中第一行有一个默认的隐式语句。

super()

注意:

  • 子类的实例化过程:子类中所有的构造函数默认都会访问父类中的空参数的构造函数。 super语句必须要定义在子类构造函数的第一行。因为父类的初始化动作要先完成。
  • 为什么子类实例化的时候要访问父类中的构造函数呢?
  • 那是因为子类继承了父类,获取到了父类中内容(属性),所以在使用父类内容之前 要先看父类是如何对自己初始化的。
  • 所以子类在构造对象时,必须访问父类中的构造函数, 为了完成这个必须的动作,就在子类中的构造函数中加了super()语句。
  • 如果父类中没有定义空参数构造函数,那么子类的构造函数必须用super明确要调用父类中哪个构造函数。
  • 父类中哪个构造函数,同时再累构造函数中如果使用this调用了本类构造函数时,那么super就没有了。 因为super和this都只能定义第一行,所以只能有一个。但是可以保证的是,子类中肯定会有其他的构造函数 访问父类的构造函数。

示例代码

class Fu{
  Fu(){
    System.out.println("Fu run");
  }
}

class Zi{
  Zi(){
    //这里有一个隐式语句,调用的就是父类中的空参数的构造函数。
    //如果父类中没有空参数的构造函数,则会报错。
    //super()
    System.out.println("Zi run");
  }
}

class ExtendsDemo{
  public function void main(){
    new Zi();
  }
}

子父类中的成员变量内存图解

子父类中的构造函数 - 子类的实例化过程图解

class Fu{
  Fu(){
    super();
    show();
    return;
  }
  void show(){
    System.out.println("fu show");
  }
}

class Zi extends Fu{
  int num = 8;
  Zi(){
    super();
    //-->通过super初始化父类内容时,子类的成员变量并未显示初始化。等super()父类初始化完毕后
    //才进行子类成员变量的显示初始化。
    System.out.println("zi cons run...."+num);
    return;
  }

  void show(){
    System.out.println("zi show..."+num);
  }
}

class ExtendsDemo{
  public static void main(String[] args){

  }
}

一个对象实例化过程

Person p = new Person();

1、JVM会读取指定路径下的Person.class文件,并加载进内存,并会先加载Person的父类 (如果有直接的父类情况下)

2、在堆内存中的开辟空间,分配地址

3、在对象空间中,对对象属性进行默认初始化。

4、调用对应的构造函数进行初始化。

5、在构造函数中,第一行会先调用父类中的构造函数进行初始化。

6、父类初始化完毕后,再对子类的属性进行显示初始化。

7、再进行子类构造函数的特定初始化

8、初始化完毕后,将地址赋值给引用变量。

三、final关键字

final 可以修饰类、方法、变量

  • final 修饰的类不可以被继承
  • final 修饰的方法不可以被覆盖
  • final 修饰的变量是一个常量,只能被赋值一次
  • 内部类只能访问被 final 修饰的局部变量。

四、抽象类

抽象类特点

1、方法只有声明没有实现,该方法就是抽象方法,需要被abstract修饰。

2、抽象方法必须定义在抽象类中,该类必须也被abstract修饰

3、抽象类不可以被实例化。只能被继承。

4、继承抽象类的子类,必须覆盖抽象类的所有抽象方法后,该子类才可以实例化。否则该子类还是抽象类。

问答

1、抽象类中有构造函数吗? 有,用于给子类对象进行初始化

2、抽象类可以不定义抽象方法吗? 可以的,但是很少见,目的就是不让该类创建对象。AWT的适配器对象就是这种类

3、抽象关键字不可以和哪些关键字共存? private/static/final

4、抽象类和一般类的区别? 一般类中不能定义抽象方法,抽象类中可以定义抽象方法。 一般类可以被实例化,抽象类不能被实例化。

5、抽象类一定是个父类吗? 是的。因为需要子类覆盖其方法后才可以对子类实例化。

五、接口

当一个抽象类中的方法都是抽象方法的时候,这时可以将该抽象类用另一种形式定义和表示,就是接口-interface

格式:定义接口使用的的关键字不是class而是interface

interface{}

接口中的成员修饰符是固定的 成员常量:public static final 成员函数:public abstract 发现接口中的成员都是public的

接口的出现将“多继承”通过另一种形式体现出来,即“多实现”

接口的实现 implements

类与类之间是继承关系,类与接口之间是实现关系

接口是一个特殊的抽象类,任然不可以被实例化,只能由实现了接口的子类覆盖了接口中所有的抽象方法后,该子类、才可以实例化。否则这个子类就是一个抽象类

在 java 中不直接支持多继承,因为会出现调用的不确定性,所以 java 将多继承机制进行改良,在 java 中变成多实现。一个类可以实现多个接口

一个类在继承另一个类的同时,还可以实现多个接口

接口的特点

1、接口是对外暴露的规则

2、接口是程序的功能扩展

3、接口的出现降低耦合性

4、接口可以用来多实现

接口与抽象类的区别

共性:都是不断抽取出来的抽象概念

区别1:抽象类体现继承关系,一个类只能但继承 接口体现实现关系,一个类可以多实现

区别2:抽象类是继承,是 is a 关系,接口是实现,是 like a 关系

区别3:抽象类可以定义非抽象方法,供子类直接使用,接口中的方法都是抽象的,接口中的成员都有固定修饰符。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

0 文章
0 评论
84960 人气
更多

推荐作者

lorenzathorton8

文章 0 评论 0

Zero

文章 0 评论 0

萧瑟寒风

文章 0 评论 0

mylayout

文章 0 评论 0

tkewei

文章 0 评论 0

17818769742

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文