Java面向对象的继承

继承

  • 继承是面向对象的三大特性之一

  • 继承基本作用:代码复用;重要作用:有了继承才能有以后的“方法的覆盖”和“多态”

  • 继承语法格式:

      [修饰符列表] class 类名 extends 父类名{
    类体
    }
  • Java语言当中的继承只支持单继承

  • 术语:

    B类继承A类,其中:

    • A类称为:父类、基类、超类、superclass
    • B类称为:子类、派生类、subclass
  • Java语言中子类继承父类:

    • 私有的不支持
    • 构造方法不支持
    • 其他数据都可以被继承
  • Java语言中假设没有显示的继承任何类,默认继承JavaSE库提供的java.lang.Object类

public class ExtendsTest01 {

    public static void main(String[] args) {

        C c1 = new C();

        c1.doSome();    // 这里调用的doSome方法是从B类中继承的
}
} class A{
public void doSome() {
System.out.println("do some !");
}
} class B extends A{ } class C extends B{ }

方法的覆盖

【回顾】Java中的·方法重载:

  • 方法重载称为Overload

  • 什么时候能用

    在同一个类当中,方法完成功能相似,建议方法同名

  • 什么样条件构成方法重载

    • 在同一个类当中
    • 方法名相同
    • 参数列表不同:类型、顺序、个数
  • 方法重载与什么无关

    • 方法的返回值类型无关
    • 方法的修饰符列表无关

【正片】方法覆盖

  • 方法覆盖【override官方】又被称作方法重写【overwrite】

  • 什么时候使用方法覆盖

    当父类中的方法已经无法满足当前子类的需求,子类有必要将父类中继承的方法进行重新编写,这个过程称为方法重写/方法覆盖

  • 代码满足什么条件会触发方法覆盖?

    • 发生在具有继承关系的父子类之间
    • 返回值类型相同,方法名相同,形参数列表相同
    • 访问权限不能更低,可以更高
    • 抛出异常不能更多,可以更少
  • 方法重新建议复制过去改【防止写错】

  • 注意:

    • 私有方法不能继承,所以不能覆盖
    • 构造方法不能继承,所以不能覆盖
    • 静态方法不存在覆盖【后面多态详讲】
    • 覆盖只针对方法,不谈属性
// 创建动物类
public class Animal { public void move() {
System.out.println("动物在移动");
}
}
// 创建猫类
public class Cat extends Animal{ // 重新父类方法
public void move() {
System.out.println("猫在走猫步");
}
}
// 创建鸟类
public class Bird extends Animal{ // 重新父类方法
public void move() {
System.out.println("鸟在飞");
}
}
public class OverrideTest01 {

    public static void main(String[] args) {

        // 创建动物对象
Animal a = new Animal();
a.move(); // 创建猫对象
Cat c = new Cat();
c.move(); // 创建鸟对象
Bird b = new Bird();
b.move();
}
}

多态

Java中多态机制【基础规则】

多态作用:

降低程序的耦合度【解耦合】,提高程序的可拓展性【尽量使用】

  • 面向对象三大特征:封装、继承、多态

  • 关于多态中涉及的概念:

    • 向上转型(upcasting)

      • 子类型 --> 父类型

        又被称为:自动类型转换

      • 通过运行一定不会出问题

    • 向下转型(downcasting)

      • 父类型 --> 子类型

        又被称为:强制类型转换【需要加强制类型转换符】

      • 通过运行可能出问题【著名异常:java.lang.ClassCastException】

    • 无论是向下转型(upcasting)还是向上转型(downcasting),两种类型之间必须要有继承关系。没有继承关系无法通过编译

    • 当调用的方法是子类型特有,在父类型当中没有。必须进行向下转型(downcasting)

    • 在向下转型(downcasting)中如何避免 ClassCastException 异常

      使用 instanceof 运算符

        (引用 instanceof 数据类型名)

      计算结果为 Boolean【布尔类型】

      • true:表示这个引用指向的对象是此数据类型
      • false:表示这个引用指向的对象不是此数据类型
    • Java规范中要求:在使用强制类型转换前,建议采用 instanceof 运算符判断,避免 ClassCastException 异常

Animal、Cat、Bird三个类之间的关系:

  • Cat 继承 Animal
  • Bird 继承 Animal
  • Cat 与 Bird无继承关系
// 创建动物类
public class Animal { public void move() {
System.out.println("动物在移动");
}
}
// 创建猫类
public class Cat extends Animal{ // 重新父类方法
public void move() {
System.out.println("猫在走猫步");
} // 不是从父类中继承的方法
// 这个方法是子类对象特有行为
public void catchMouse() {
System.out.println("猫抓老鼠");
}
}
// 创建鸟类
public class Bird extends Animal{ // 重新父类方法
public void move() {
System.out.println("鸟在飞");
} // 子类对象特有行为
public void fly() {
System.out.println("Bird fly !");
}
}
public class Test {

    public static void main(String[] args) {

        // 以前编写的程序

        // 创建动物对象
Animal a1 = new Animal();
a1.move(); // 创建猫对象
Cat c1 = new Cat();
c1.move();
c1.catchMouse(); // 创建鸟对象
Bird b1 = new Bird();
b1.move(); // 使用动态机制
System.out.println("-----以下使用动态机制----"); Animal a2 = new Cat(); // 想象 long num = 10;
// Cat is a Animal
// new Cat()创建的对象类型是Cat,Animal a2中 a2 引用的数据类型是Animal,可见它们进行类型转换
// 子类型转换父类型,称为向上转型(upcasting),或者自动类型转换 // Bird b2 = new Cat(); Bird与Cat无继承关系 // 编译器只会把a2类型视作Animal
// 运行时是看底层的实际内容
a2.move(); // 猫在走猫步 // a2.catchMouse(); 报错
// 编译器检查为Animal类型,Animal中没有catchMouse()方法,导致静态绑定失败 // 需求:需要a2去执行catchMouse()方法
// 可以通过向下转型(downcasting),强制转换,同样需要两者有继承关系
Cat c2 = (Cat)a2;
c2.catchMouse(); // 父类型引用指向子类型对象【多态】
// 以下程序编译无错语法允许,但运行阶段报错JVM堆内存实际存在的是Bird对象
// 类型之间不存在如何继承关系,会发生著名异常:java.lang.ClassCastException
// 触发一般在向下转型(downcasting),一定注意 // Animal a3 = new Bird();
// Cat c3 = (Cat)a3; // c3.catchMouse(); 报错 著名异常:java.lang.ClassCastException // 避免ClassCastException
Animal a3 = new Bird(); if(a3 instanceof Cat) {
Cat c3 = (Cat)a3;
c3.catchMouse();
}else if(a3 instanceof Bird){
Bird b3 = (Bird)a3;
b3.fly();
} }
}
  1. java程序永远都分为编译阶段和运行阶段
  2. 先分析编译阶段,再分析运行阶段,编译无法通过,根本无法运行
  3. 编译阶段编译器检查a2这个引用的数据类型是Animal,由于Animal.class字节码当中有move()方法,所以编译通过,这个过程我们称为静态绑定,编译阶段绑定。只有静态绑定成功之后才有程序运行
  4. 在程序运行阶段,JVM堆内存中真实创建的对象是Cat对象,那么上述程序中 a2.move(); 一定调用Cat对象的move()方法【方法重写无关】,称为动态绑定,运行阶段绑定
  5. 无论重写与否,运行阶段只与底层实际关联

父类型引用指向子类型对象这种机制导致程序在编译阶段绑定和运行阶段绑定两种不同的形态,这种机制可以成为一种动态语法机制


Java面向对象



学习笔记--Java面向对象的继承的更多相关文章

  1. 我的Java学习笔记-Java面向对象

    今天来学习Java的面向对象特性,由于与C#的面向对象类似,不需详细学习 一.Java继承 继承可以使用 extends 和 implements 这两个关键字来实现继承. extends:类的继承是 ...

  2. C++ Primer 学习笔记_69_面向对象编程 --继承情况下的类作用域

    面向对象编程 --继承情况下的类作用域 引言: 在继承情况下,派生类的作用域嵌套在基类作用域中:假设不能在派生类作用域中确定名字,就在外围基类作用域中查找该名字的定义. 正是这样的类作用域的层次嵌套使 ...

  3. 学习笔记-Java面向对象

    学习来源: B站[狂神说Java]Java零基础学习视频通俗易懂 static关键字详解 package com.oop.demo07; //static public class Student{ ...

  4. Java学习笔记之---面向对象

    Java学习笔记之---面向对象 (一)封装 (1)封装的优点 良好的封装能够减少耦合. 类内部的结构可以自由修改. 可以对成员变量进行更精确的控制. 隐藏信息,实现细节. (2)实现封装的步骤 1. ...

  5. [java学习笔记]java语言核心----面向对象之this关键字

    一.this关键字 体现:当成员变量和函数的局部变量重名时,可以使用this关键字来区别:在构造函数中调用其它构造函数 原理:         代表的是当前对象.         this就是所在函数 ...

  6. 《Java核心技术·卷Ⅰ:基础知识(原版10》学习笔记 第5章 继承

    <Java核心技术·卷Ⅰ:基础知识(原版10>学习笔记 第5章 继承 目录 <Java核心技术·卷Ⅰ:基础知识(原版10>学习笔记 第5章 继承 5.1 类.超类和子类 5.1 ...

  7. [java学习笔记]java语言核心----面向对象之构造函数

    1.构造函数概念 特点: 函数名与类名相同 不用定义返回值类型 没有具体的返回值 作用:                给对象进行初始化 注意: 默认构造函数 多个构造函数是以重载出现的 一个类中如果 ...

  8. Lua学习笔记:面向对象

    Lua学习笔记:面向对象 https://blog.csdn.net/liutianshx2012/article/details/41921077 Lua 中只存在表(Table)这么唯一一种数据结 ...

  9. ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET MVC 学习笔记-6.异步控制器 ASP.NET MVC 学习笔记-5.Controller与View的数据传递 ASP.NET MVC 学习笔记-4.ASP.NET MVC中Ajax的应用 ASP.NET MVC 学习笔记-3.面向对象设计原则

    ASP.NET MVC 学习笔记-7.自定义配置信息   ASP.NET程序中的web.config文件中,在appSettings这个配置节中能够保存一些配置,比如, 1 <appSettin ...

  10. UML和模式应用学习笔记-1(面向对象分析和设计)

    UML和模式应用学习笔记-1(面向对象分析和设计) 而只是对情节的记录:此处的用例场景为:游戏者请求掷骰子.系统展示结果:如果骰子的总点数是7,则游戏者赢得游戏,否则为输 (2)定义领域模型:在领域模 ...

随机推荐

  1. 微信开发者工具拉取gitlab远程代码报Pull failed原因分析:

    可能出现的原因: 本地主机上没有安装node node下载地址: 1 https://nodejs.org/zh-cn/download/ 没有保存gitlab的用户名和密码

  2. Vue cli路由

    上面是将Forecast组件作为了Home的子组件使用,现在我们将其作为一个路由组件使用. 在router/index.js路由系统注册路由: { path: '/forecast', name: ' ...

  3. Opencv笔记(12)傅里叶变换

    在之前了解的OpenCV为我们实现的图像变换,这些本质上是从图像到输出图像的映射,即输入仍是一幅图像.本章的傅里叶变换,输出数组的值在含义上和原图像的强度值大不相同,是输入图像的频域表示. cv::d ...

  4. Linux-线程优先级学习

    概念 Linux系统中常用的几种调度类为SCHED_NORMAL.SCHED_FIFO.SCHED_RR. SCHED_NORMAL:用于普通线程的调度类 SCHED_FIFO和SCHED_RR是用于 ...

  5. LiteOS基础学习

    1 IDE环境安装 目的:安装LiteOS IDE,并且是使用仿真方式运行. 1.1 IDE安装 HUAWEI LiteOS Studio安装 (gitee.io) 1.2 中文安装 HUAWEI L ...

  6. node child_process模块exec

    child_process是Node.js自带的核心模块之一,无需额外安装即可使用. child_process模块提供了创建子进程的功能,可以在Node.js中执行外部命令.脚本文件等,并与其进行交 ...

  7. Vector + ClickHouse 收集日志

    目前业界的日志生态,最常用的是 ELK,其次就是 ClickHouse,本文会演示如何使用 Vector + ClickHouse 来采集 Nginx 日志并做清洗,最终写入 ClickHouse.至 ...

  8. shell基础概述

    1.0 编程的目的 计算机的发明,是为了用机器取代/解放人力,而编程的目的则是将人类的思想流程按照某种能够被计算机识别的表达方式传递给计算机,从而达到让计算机能够像人脑/电脑一样自动执行的效果. 编程 ...

  9. String和StringBuffer、StringBuilder的区别是什么?String为什么是不可变的

    a.可变性:String类中使用字符数组保存字符串,private  final   char   value[],所以string对象是不可变的.StringBuilder与StringBuffer ...

  10. ISCSI配置与挂载

    ISCSI介绍 iSCSI使用 TCP/IP 协议,来提供网络存储. 客户端挂载后,可以对其进行分区,进行格式化,就好像是安装在本机上的硬盘一样. 为了保证传输速率,通常采用光纤. 配置环境 Cent ...