1、继承概述

继承是Java面向对象的三大特征之一,是比较重要的一部分,与后面的多态有着直接的关系。继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。

①、Java继承的特点:

Java只支持单继承,不支持多继承(如A继承B,A继承C),但支持多层继承(如A继承B,B继承C)。

子类拥有父类非private的属性,方法。(其实子类继承父类后,仍然认为获取了父类的private结构,只是因为封装的影响,使得子类不能直接调用父类的结构而已)

子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。

子类可以用自己的方式实现父类的方法。

提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系)。

②、继承的好处:

减少代码的冗余,提高代码的复用性。

便于功能的扩展。

为后面多态的使用提供了前提。

③、类的继承格式:

在Java中通过 extends 关键字来实现继承关系,形式如下:

class 父类 {
    属性、方法
}

class 子类 extends 父类 {
    属性、方法
}

提到Java的继承,肯定离不开this,super关键字和构造器的使用,下面来介绍一下:

2、this、super关键字

this关键字:表示引用当前对象或正在创建的对象。可用于调用本类的属性、方法、构造器。

public class Test {
    public static void main(String[] args) {
        Father father=new Father("tang_hao",20);
        father.show();
    }
}
class Father{
    String name;
    int age;

    public Father() {
    }

    public Father(String name) {
        //调用本类的无参构造器
        this();
        this.name = name;
    }

    public Father(String name, int age) {
        //调用本类的有参构造器
        this(name);
        this.age = age;
    }

    public void show(){
        System.out.println("name"+this.name+",age"+this.age);
    }
}

super关键字:表示引用当前对象的父类。可用于调用父类的属性、方法、构造器。

public class Test {

    public static void main(String[] args) {
        Son son=new Son();
        son.show();
    }
}
class Father{
    String name="Father";
    int age=40;

    public Father() {
        System.out.println("调用了父类的无参构造器");
    }

    public void show(){
        System.out.println("父类的Show方法");
    }
}

class Son extends Father{
    String name="Son";
    int age=20;

    public Son() {
        //调用父类构造器
        super();
    }

    public void show(){
        System.out.println("子类的Show方法");
        System.out.println("本类属性:"+this.name+","+this.age);
        //调用父类方法
        super.show();
        System.out.println("父类属性:"+super.name+","+super.age);
    }
}

注意:在使用this、super调用构造器的时候,this、super语句必须放在构造方法的第一行,否则编译会报错。不能在子类中使用父类构造方法名来调用父类构造方法。 父类的构造方法不被子类继承。调用父类的构造方法的唯一途径是使用 super 关键字,如果子类中没显式调用,则编译器自动将 super();也就是说会一直调到Object类,因为Object是所有类的父类。静态方法中不能使用 super 关键字。

3、构造器

前面讲到子类可以继承父类的非private修饰的属性和方法,那么我们思考一下?父类的构造器能够被子类继承吗?答案是:不能!对于构造器而言,它只能够被调用,而不能被继承。 调用父类的构造方法我们使用super()即可。

我们先来看一个示例:

public class Father {
    protected String name;//姓名
    protected int age;//年龄

    public Father(){
        System.out.println("Father constructor");
    }

    public void eat(){
        System.out.println("Father eat...");
    }

    public void sleep(){
        System.out.println("Father sleep...");
    }
}

class Son extends Father{
    protected String name;//姓名
    protected int age;//年龄

    public Son() {
        System.out.println("Son constructor");
    }

    public void eat() {
        System.out.println("Son eat...");
    }

    public void sleep() {
        System.out.println("Son sleep...");
    }

    public static void main(String[] args) {
        Son son=new Son();
        son.eat();
        son.sleep();
    }
}

运行结果:

从运行的结果来看,我们只new了Son的实例,但是却调用父类的无参构造器,而且先输出了父类构造器的语句。这是因为:如果子类中没显式调用父类构造器,则编译器会自动在构造器方法第一行加上super()。

通过这个示例可以看出,构建过程是从父类“向外”扩散的,也就是从父类开始向子类一级一级地完成构建。而且我们并没有显示的引用父类的构造器,这就是java的聪明之处:编译器会默认给子类调用父类的构造器。

但是,这个默认调用父类的构造器是有前提的:父类有默认构造器。如果父类没有默认构造器,我们就要必须显示的使用super()来调用父类构造器,否则编译器会报错:无法找到符合父类形式的构造器。

public class Father {
    protected String name;//姓名
    protected int age;//年龄

    public Father(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void eat(){
        System.out.println("Father eat...");
    }

    public void sleep(){
        System.out.println("Father sleep...");
    }
}

class Son extends Father{
    protected String name;//姓名
    protected int age;//年龄

    public Son(String name, int age) {
        //这里父类没有默认构造器,所以必须显式的使用super()
        super("tang_hao",22);
        this.name = name;
        this.age = age;
    }

    public void eat() {
        System.out.println("Son eat...");
    }

    public void sleep() {
        System.out.println("Son sleep...");
    }

    public static void main(String[] args) {
        Son son=new Son("tang_hao",20);
        son.eat();
        son.sleep();
    }
}

小结:子类会默认使用super()调用父类默认构造器,如果父类没有默认构造器,则子类必须显式的使用super()来调用父类构造器,而且super()必须要放在子类构造方法的第一行。

4、继承带来的问题

  1. 子类与父类存在严重的耦合关系。
  2. 继承破坏了父类的封装性。
  3. 子类继承父类的属性和方法,也就说明可以从子类中恶意修改父类的属性和方法。

所以能不使用继承关系就尽量不要使用继承。

5、何时使用继承

  1. 子类需要额外增加属性,而不仅仅是属性值的改变。
  2. 子类需要增加自己独有的行为方式(包括增加新的方法或重写父类的方法)。

夯实Java基础(三)——面向对象之继承的更多相关文章

  1. 夯实Java基础系列1:Java面向对象三大特性(基础篇)

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 [https://github.com/h2pl/Java-Tutorial](https: ...

  2. 夯实Java基础系列9:深入理解Class类和Object类

    目录 Java中Class类及用法 Class类原理 如何获得一个Class类对象 使用Class类的对象来生成目标类的实例 Object类 类构造器public Object(); register ...

  3. 夯实Java基础系列目录

    自进入大学以来,学习的编程语言从最初的C语言.C++,到后来的Java,. NET.而在学习编程语言的同时也逐渐决定了以后自己要学习的是哪一门语言(Java).到现在为止,学习Java语言也有很长一段 ...

  4. 夯实Java基础系列3:一文搞懂String常见面试题,从基础到实战,更有原理分析和源码解析!

    目录 目录 string基础 Java String 类 创建字符串 StringDemo.java 文件代码: String基本用法 创建String对象的常用方法 String中常用的方法,用法如 ...

  5. 夯实Java基础系列6:一文搞懂抽象类和接口,从基础到面试题,揭秘其本质区别!

    目录 抽象类介绍 为什么要用抽象类 一个抽象类小故事 一个抽象类小游戏 接口介绍 接口与类相似点: 接口与类的区别: 接口特性 抽象类和接口的区别 接口的使用: 接口最佳实践:设计模式中的工厂模式 接 ...

  6. 夯实Java基础系列7:一文读懂Java 代码块和执行顺序

    目录 Java中的构造方法 构造方法简介 构造方法实例 例 1 例 2 Java中的几种构造方法详解 普通构造方法 默认构造方法 重载构造方法 java子类构造方法调用父类构造方法 Java中的代码块 ...

  7. 夯实Java基础系列13:深入理解Java中的泛型

    目录 泛型概述 一个栗子 特性 泛型的使用方式 泛型类 泛型接口 泛型通配符 泛型方法 泛型方法的基本用法 类中的泛型方法 泛型方法与可变参数 静态方法与泛型 泛型方法总结 泛型上下边界 泛型常见面试 ...

  8. 夯实Java基础系列14:深入理解Java枚举类

    目录 初探枚举类 枚举类-语法 枚举类的具体使用 使用枚举类的注意事项 枚举类的实现原理 枚举类实战 实战一无参 实战二有一参 实战三有两参 枚举类总结 枚举 API 总结 参考文章 微信公众号 Ja ...

  9. 夯实Java基础系列15:Java注解简介和最佳实践

    Java注解简介 注解如同标签 Java 注解概述 什么是注解? 注解的用处 注解的原理 元注解 JDK里的注解 注解处理器实战 不同类型的注解 类注解 方法注解 参数注解 变量注解 Java注解相关 ...

  10. Java工程师学习指南第1部分:夯实Java基础系列

    点击关注上方"Java技术江湖",设为"置顶或星标",第一时间送达技术干货. 本文整理了微信公众号[Java技术江湖]发表和转载过的Java优质文章,想看到更多 ...

随机推荐

  1. GO代码生成代码小思小试

    推进需求 GO 项目,可整体生成一个运行文件到处跑,是极爽之事.但如果有资源文件要得带着跑,则破坏了这种体验. 例如下边这个项目结构,resource 目录下为资源文件,main.go 中会通过路径引 ...

  2. 通过CDN引入jQuery的几种方式

    百度 CDN <head> <script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js" ...

  3. TCP/IP网络协议

    OSI七层模型 OSI采用了分层的结构化技术,共分七层,物理层.数据链路层.网络层.传输层.会话层.表示层.应用层. TCP/IP模型 OSI模型比较复杂且学术化,所以我们实际使用的TCP/IP模型, ...

  4. kd树原理及实现

    常用来作空间划分及近邻搜索,是二叉空间划分树的一个特例.通常,对于维度为k,数据点数为N的数据集,kd树适用于N≫2的k次方的情形. 1维数据的查询 假设在数据库的表格T中存储了学生的语文成绩chin ...

  5. ICC中用Tcl脚本给版图中的Port/Terminal加Label的方法

    本文转自:自己的微信公众号<数字集成电路设计及EDA教程> 里面主要讲解数字IC前端.后端.DFT.低功耗设计以及验证等相关知识,并且讲解了其中用到的各种EDA工具的教程. 考虑到微信公众 ...

  6. 如何编写无须人工干预的shell脚本

    在使用基本的一些shell命令时,机器需要与人进行互动来确定命令的执行.比如 cp test.txt boo/test.txt,会询问是否覆盖?ssh远程登陆时,需要输入人工密码后,才可以继续执行ss ...

  7. MyBatis从入门到精通:第一章配置文件log4j.properties

    配置文件: #全局配置 log4j.rootLogger=ERROR,stdout #MyBatis日志配置 log4j.logger.tk.mybatis.simple.mapper=TRACE # ...

  8. DAX 第二篇:计算上下文

    计算上下文是计算公式的环境,任何DAX表达式都是在上下文中求值的.行上下文和筛选上下文是DAX中仅有的上下文类型,把这两种上下文称为计算上下文.计算上下文用于限定公式计算的环境,当上下文变化时,相同的 ...

  9. TF项目实战(SSD目标检测)-VOC2007

    TF项目实战(SSD目标检测)-VOC2007 训练好的模型和代码会公布在网上: 步骤: 1.代码地址:https://github.com/balancap/SSD-Tensorflow 2.解压s ...

  10. 洛谷P1640 [SCOI2010]连续攻击游戏 题解

    题目链接: https://www.luogu.org/problemnew/show/P1640 分析: 这道题用二分图来解决即可.应该可以作为网络流中的模板题来食用, 每一个武器有两个属性,但是只 ...