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. 鸿蒙HarmonyOS实战-Stage模型(进程模型)

    前言 进程是计算机中运行的程序的实例.它是操作系统对正在执行的程序的一种抽象概念.每个进程都有自己的独立内存空间.运行状态和执行上下文.进程可以包含一个或多个线程,每个线程可以独立执行一部分任务.操作 ...

  2. .NET6之MiniAPI(九):基于角色的身份验证和授权

    身份验证是这样一个过程:由用户提供凭据,然后将其与存储在操作系统.数据库.应用或资源中的凭据进行比较. 在授权过程中,如果凭据匹配,则用户身份验证成功,可执行已向其授权的操作. 授权指判断允许用户执行 ...

  3. C#中接口的显式实现与隐式实现及其相关应用案例

    C#中接口的显式实现与隐式实现 最近在学习演化一款游戏项目框架时候,框架作者巧妙使用接口中方法的显式实现来变相对接口中方法进行"密封",增加实现接口的类访问方法的"成本& ...

  4. 算法学习笔记(46): 离散余弦变换(DCT)

    前置知识:离散傅里叶变换 傅里叶变换在上文中更多的是 OI 中的理解以及应用.但是傅里叶变换奥秘还很多. 回顾 \(\omega_n\) 在傅里叶变换中的定义:\(e^{i \frac {2\pi} ...

  5. minos 1.1 内存虚拟化——hyp

    首发公号:Rand_cs minos 1.1 内存虚拟化--hyp 内存虚拟化,目前理解主要两方面: 内存管理,没有虚拟化的情况时,对于 Linux 内核运行在物理硬件之上,内核需要管理物理内存,需要 ...

  6. 使用 OpenTelemetry 构建可观测性 06 - 生态系统

    过去的五篇文章讨论了如何使用 OpenTelemetry 来构建可观测性的技术细节.我认为在本博文系列的结尾介绍有关 OTel 生态系统的信息,为读者提供更全面的了解非常重要.OpenTelemetr ...

  7. MySQL数据库开发(2)

    单表查询 单表查询即对单个表进行查询. 单表查询的语法 SELECT 字段1,字段2... FROM 表名 WHERE 条件 GROUP BY field HAVING 筛选 ORDER BY fie ...

  8. 2. Elasticsearch 使用插件和kibana操作

    引言 在上一篇文章中1. Elasticsearch 入门安装与部署 已经教了大家如何在linux系统中安装和启动Elasticsearch,本文就带大家一起学习如何操作 Elasticsearch. ...

  9. 订单号规则,不能重复。redis去重 redis集合set应用

    订单号规则,不能重复.redis去重 redis集合set应用 redis锁定商品解决并发售卖问题 RedisUtil工具类https://www.cnblogs.com/oktokeep/p/179 ...

  10. window10 java环境变量配置

    window10 此电脑 右击属性 相关设置 高级系统配置 点击右下的 环境变量 在系统变量中新增JAVA_HOME=D:\Program Files\Java\jdk1.8.0_25 在系统变量中修 ...