JavaSE学习进阶day2_02 抽象类和接口

news2024/12/30 2:30:43

第四章 抽象类

4.1 概述

4.1.1 抽象类引入

先看一张图:

这张图时之前学习继承时用的,但是现在有一个疑问,吃饭这个行为猫和狗都有,但是它们吃的东西却又不同,这个时候我们不能确定父类吃饭这个方法到底该写什么,这是就要用到抽象方法。

父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明还有意义,而方法主体则没有存在的意义了(因为子类对象会调用自己重写的方法)。换句话说,父类可能知道子类应该有哪个功能,但是功能具体怎么实现父类是不清楚的(由子类自己决定),父类只需要提供一个没有方法体的定义即可,具体实现交给子类自己去实现。我们把没有方法体的方法称为抽象方法。Java语法规定,包含抽象方法的类就是抽象类!!。

  • 抽象方法没有方法体的方法。

  • 抽象类包含抽象方法的类

4.2 abstract使用格式

abstract是抽象的意思,用于修饰方法方法和类,修饰的方法是抽象方法,修饰的类是抽象类。

4.2.1 抽象方法

使用abstract 关键字修饰方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体

定义格式:

修饰符 abstract 返回值类型 方法名 (参数列表);//没有方法体,直接以分号结束!!

代码举例:

public abstract void run();

4.2.2 抽象类

如果一个类包含抽象方法,那么该类必须是抽象类。注意:抽象类不一定有抽象方法,但是有抽象方法的类必须定义成抽象类。

定义格式:

abstract class 类名字 { 
  
}

代码举例:

public abstract class Animal {
    public abstract void run();
}

4.2.3 抽象类的使用

要求:继承抽象类的子类必须重写父类所有的抽象方法。否则,该子类也必须声明为抽象类(这第二种基本用不到,了解即可)。

代码举例:

// 父类,抽象类
abstract class Employee {
    private String id;
    private String name;
    private double salary;
    
    public Employee() {
    }
    
    public Employee(String id, String name, double salary) {
        this.id = id;
        this.name = name;
        this.salary = salary;
    }
    
    // 抽象方法
    // 抽象方法必须要放在抽象类中
    abstract public void work();
}
​
// 定义一个子类继承抽象类
class Manager extends Employee {
    public Manager() {
    }
    public Manager(String id, String name, double salary) {
        super(id, name, salary);
    }
    // 2.重写父类的抽象方法
    @Override
    public void work() {
        System.out.println("管理其他人");
    }
}
​
// 定义一个子类继承抽象类
class Cook extends Employee {
    public Cook() {
    }
    public Cook(String id, String name, double salary) {
        super(id, name, salary);
    }
    @Override
    public void work() {
        System.out.println("厨师炒菜多加点盐...");
    }
}
​
// 测试类
public class Demo10 {
    public static void main(String[] args) {
        // 创建抽象类,抽象类不能创建对象!!
        // 假设抽象类让我们创建对象,里面的抽象方法没有方法体,无法执行.所以不让我们创建对象!!
//      Employee e = new Employee();
//      e.work();
        
        // 3.创建子类
        Manager m = new Manager();
        m.work();
        
        Cook c = new Cook("ap002", "库克", 1);
        c.work();
    }
}

此时的方法重写,是子类对父类抽象方法的完成实现,我们将这种方法重写的操作,也叫做实现方法

4.3 抽象类的特征

抽象类的特征总结起来可以说是 有得有失

有得:抽象类得到了拥有抽象方法的能力。

有失:抽象类失去了创建对象的能力!!。

其他成员(构造方法,实例方法,静态方法等)抽象类都是具备的。

4.4 抽象类的细节

不需要背,只要当idea报错之后,知道如何修改即可。好的,现在又到了idea使用的妙招了!!那么idea报错后怎么修改呢?(重点)

现在我们创建一个动物类(还不是抽象类),并在该类里写一个的抽象方法:

先不要加abstract关键字,这样写一个普通的方法,但是以分号结尾,没有方法体。

点击eat这个方法,按住:alt+回车,如下:

此时出现两个提示,第一个提示时说给方法加上方法体,这个不是我们需要的,我们要的是第二个。将eat这个方法改为抽象abstract方法

此时我们发现idea还自动把类加上了abstract关键字。这个就是idea的好处,这不又掌握了一个快捷键:alt+回车

关于抽象类的使用,以下为语法上要注意的细节,虽然条目较多,但若理解了抽象的本质,无需死记硬背。

  1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。

    理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。

  2. 抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的。

    理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。

  3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类

    理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。

  4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则子类也必须定义成抽象类(这种基本用不到,了解即可),编译无法通过而报错。

    理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。

  5. 抽象类存在的意义是为了被子类继承。

    理解:抽象类中已经实现的是模板中确定的成员,抽象类不确定如何实现的定义成抽象方法,交给具体的子类去实现。

4.5 抽象类存在的意义

抽象类存在的意义是为了被子类继承,否则抽象类将毫无意义。抽象类可以强制让子类,一定要按照父类规定的格式进行重写。

第五章 接口

5.1 概述

我们已经学完了抽象类,抽象类中可以用抽象方法,也可以有普通方法,构造方法,成员变量等。那么什么是接口呢?接口是更加彻底的抽象,JDK7之前,包括JDK7,接口中全部是抽象方法。接口同样是不能创建对象的

首先搞清楚一个问题:为什么要有接口?如下:

我们发现青蛙和狗可以游泳,而兔子却不可以,因此不能把游泳这个行为定义在父类——动物类中,但是如果在青蛙和狗类又单独实现游泳这个方法的话会带来一些问题,就像前面说的,因为你写的游泳和别人写的游泳可能格式不一样,返回类型不一样,因此调用的时候引发一些问题。这个时候接口就是为了解决这个问题。

通过上面的叙述我们总结接口的作用:接口是独立于继承体系以外的共性内容,想让哪个类拥有对应的功能,就实现对应的接口就可以了。

5.2 定义格式

//接口的定义格式:
interface 接口名称{
    // 抽象方法
}
​
// 接口的声明:interface
// 接口名称:首字母大写,满足“驼峰模式”

5.3 接口成分的特点

在JDK7,包括JDK7之前,接口中的只有包含:抽象方法和常量

5.3.1.抽象方法

注意:接口中的抽象方法默认会自动加上public abstract修饰,程序员无需自己手写!! ​ 按照规范:以后接口中的抽象方法建议不要写上public abstract。因为没有必要啊,默认会加上。但是既然是初次学习为了方便阅读,还是加上为好,等你把这个特性记熟了就用不着这么写了。

5.3.2 常量

在接口中定义的成员变量默认会加上: public static final修饰。也就是说在接口中定义的成员变量实际上是一个常变量”。这里是使用public static final修饰后,变量值就不可被修改,并且是静态化的变量可以直接用接口名访问,所以也叫常量。常量必须要给初始值。常量命名规范建议字母全部大写,多个单词用下划线连接。之前在基础班学到标识符的命名规则那个下划线就在这里体现出来了。

注意上面提到必须初始化,如下:

在上述接口中定义的一个未初始化的变量会报错,因为没有赋值。如下:

 这个刚在上一小节学习final关键字修饰成员变量(不是局部变量)的时候就已经强调过了。

给它赋值以后就不会报错了,这是初次学习容易犯错的一个知识点!

5.3.3 案例演示

public interface InterF {
    // 抽象方法!
    //    public abstract void run();
    void run();
​
    //    public abstract String getName();
    String getName();
​
    //    public abstract int add(int a , int b);
    int add(int a , int b);
​
​
    // 它的最终写法是:
    // public static final int AGE = 12 ;
    int AGE  = 12; //常量
    String SCHOOL_NAME = "黑马程序员";
​
}

5.4 基本的实现

5.4.1 实现接口的概述

我们知道类与类之间是继承关系!类与接口的关系为实现关系,即类实现接口,该类可以称为接口的实现类,也可以称为接口的子类。实现的动作类似继承,格式相仿,只是关键字不同,实现使用 implements关键字。

5.4.2 实现接口的格式

/**接口的实现:
    在Java中接口是被实现的,实现接口的类称为实现类。
    实现类的格式:*/
class 类名 implements 接口1,接口2,接口3...{
​
}

从上面格式可以看出,接口是可以被多实现的。大家可以想一想为什么呢?

5.4.3 类实现接口的要求和意义

  1. 必须重写实现的全部接口中所有抽象方法

  2. 如果一个类实现了接口,但是没有重写完全部接口的全部抽象方法,这个类也必须定义成抽象类。这个和抽象类极为相似,但他们之间又有不同。显然这个不是我们想要的,因此在今后的开发中我们基本都要重写所有的抽象方法。

  3. 意义:接口体现的是一种规范,接口对实现类是一种强制性的约束,要么全部完成接口申明的功能,要么自己也定义成抽象类。这正是一种强制性的规范。

5.4.4 类与接口基本实现案例

假如我们定义一个运动员的接口(规范),代码如下:

/**
   接口:接口体现的是规范。
 * */
public interface SportMan {
    void run(); // 抽象方法,跑步。
    void law(); // 抽象方法,遵守法律。
    String compittion(String project);  // 抽象方法,比赛。
}

接下来定义一个乒乓球运动员类,实现接口,实现接口的实现类代码如下:

package com.itheima._03接口的实现;
/**
 * 接口的实现:
 *    在Java中接口是被实现的,实现接口的类称为实现类。
 *    实现类的格式:
 *      class 类名 implements 接口1,接口2,接口3...{
 *
 *
 *      }
 * */
public class PingPongMan  implements SportMan {
    @Override
    public void run() {
        System.out.println("乒乓球运动员稍微跑一下!!");
    }
​
    @Override
    public void law() {
        System.out.println("乒乓球运动员守法!");
    }
​
    @Override
    public String compittion(String project) {
        return "参加"+project+"得金牌!";
    }
}

测试代码

​
public class TestMain {
    public static void main(String[] args) {
        // 创建实现类对象。
        PingPongMan zjk = new PingPongMan();
        zjk.run();
        zjk.law();
        System.out.println(zjk.compittion("全球乒乓球比赛"));
​
    }
}

5.4.5 类与接口的多实现案例

类与接口之间的关系是多实现的,一个类可以同时实现多个接口。

首先我们先定义两个接口,代码如下:

/** 法律规范:接口*/
public interface Law {
    void rule();
}
​
/** 这一个运动员的规范:接口*/
public interface SportMan {
    void run();
}
​

然后定义一个实现类:

/**
 * Java中接口是可以被多实现的:
 *    一个类可以实现多个接口: Law, SportMan
 *
 * */
public class JumpMan implements Law ,SportMan {
    @Override
    public void rule() {
        System.out.println("尊长守法");
    }
​
    @Override
    public void run() {
        System.out.println("训练跑步!");
    }
}

从上面可以看出类与接口之间是可以多实现的,我们可以理解成实现多个规范,这是合理的。

5.5 接口与接口的多继承

Java中,接口与接口之间是可以多继承的:也就是一个接口可以同时继承多个接口。大家一定要注意:但是类与类只能单继承,但是类与类又能多层继承,注意是多层继承,不是多继承!!

类与接口是实现关系

接口与接口是继承关系

接口继承接口就是把其他接口的抽象方法与本接口进行了合并。但是不是说要在子接口重写父接口的所有抽象方法,二是在它的实现类中重写所有继承接口的抽象方法(包括父接口,子接口里的所有方法)

案例演示:

public interface Abc {
    void go();
    void test();
}
​
/** 法律规范:接口*/
public interface Law {
    void rule();
    void test();
}
​
 *
 *  总结:
 *     接口与类之间是多实现的。
 *     接口与接口之间是多继承的。
 * */
public interface SportMan extends Law , Abc {
    void run();
}

5.6接口的细节

不需要背,只要当idea报错之后,知道如何修改即可。

关于接口的使用,以下为语法上要注意的细节,虽然条目较多,但若理解了抽象的本质,无需死记硬背。

  1. 当两个接口中存在相同抽象方法的时候,该怎么办?

只要重写一次即可。此时重写的方法,既表示重写1接口的,也表示重写2接口的。

  1. 实现类能不能继承A类的时候,同时实现其他接口呢?

继承的父类,就好比是亲爸爸一样 实现的接口,就好比是干爹一样 可以继承一个类的同时,再实现多个接口,只不过,要把接口里面所有的抽象方法,全部实现。

  1. 实现类能不能继承一个抽象类的时候,同时实现其他接口呢?

实现类可以继承一个抽象类的同时,再实现其他多个接口,只不过要把里面所有的抽象方法全部重写。

  1. 实现类Zi,实现了一个接口,还继承了一个Fu类。假设在接口中有一个方法,父类中也有一个相同的方法。子类如何操作呢?

处理办法一:如果父类中的方法体,能满足当前业务的需求,在子类中可以不用重写。 处理办法二:如果父类中的方法体,不能满足当前业务的需求,需要在子类中重写。

  1. 如果一个接口中,有10个抽象方法,但是我在实现类中,只需要用其中一个,该怎么办?

可以在接口跟实现类中间,新建一个中间类(适配器类) 让这个适配器类去实现接口,对接口里面的所有的方法做空重写。 让子类继承这个适配器类,想要用到哪个方法,就重写哪个方法。 因为中间类没有什么实际的意义,所以一般会把中间类定义为抽象的,不让外界创建对象 私有化构造方法 --- 反射,即使私有化构造方法,在外界也可以创建对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/389066.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据库分库分表策略

一、MySQL扩展具体的实现方式 随着业务规模的不断扩大,需要选择合适的方案去应对数据规模的增长,以应对逐渐增长的访问压力和数据量。 关于数据库的扩展主要包括:业务拆分、主从复制,数据库分库与分表。这篇文章主要讲述数据库分库…

03-SQLPlus的常用命令和使用

本章内容讲解SQLPlus的常用命令使用方法,参数的设置,帮助的使用,详细讲解如下: 登录SQL*Plus DOS方式登录SQL*Plus C:\>sqlplus 提示输入用户名、密码 C:\>sqlplus scott/tiger 连到默认数据库,注册表或环境变量中设 …

Blender——植物生长动画制作

效果图前言参考链接:https://www.bilibili.com/video/BV1aY411G7bk/?spm_id_from333.788.recommend_more_video.10&vd_source5212838c127b01db69dcc8b2d27ca517建议Blender的版本在3.0.0或以上。制作完成的植物生长动画blender文件下载:https://dow…

SpringCloud之ElasticSearch笔记

ElasticSearch 初识ElasticSearch ElasticSearch是什么 ElasticSearch一个基于Lucene的底层的开源的分布式搜索引擎,可用来实现搜索,日志统计,分析,系统监控 正向索引和倒排索引 正向索引:逐条扫描(my…

Databend v1.0 Release 正式发布

尊敬的 Databenders,在 Databend Labs 成立两周年之际,我们非常高兴地宣布 Databend v1.0 正式发布。 Databend 社区一直在致力于解决大数据分析的成本和复杂度问题,并正在被顶级场景和顶级需求所推动。 根据可统计信息,每天约 7…

2023年“中银杯”安徽省职业院校技能大赛网络安全A模块全过程解析

A模块基础设施设置/安全加固(200分) 一、项目和任务描述: 假定你是某企业的网络安全工程师,对于企业的服务器系统,根据任务要求确保各服务正常运行,并通过综合运用登录和密码策略、流量完整性保护策略、事件监控策略、防火墙策略等多种安全策略来提升服务器系统的网络安全…

K8S 实用工具之三 - 图形化 UI Lens

开篇 📜 引言: 磨刀不误砍柴工工欲善其事必先利其器 第一篇:《K8S 实用工具之一 - 如何合并多个 kubeconfig?》第二篇:《K8S 实用工具之二 - 终端 UI K9S》 像我这种,kubectl 用的不是非常溜,经…

指针面试笔试题练习

前言 🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨ 🐻推荐专栏: 🍔🍟🌯 c语言进阶 🔑个人信条: 🌵知行合一 🍉本篇简介:>:介绍c语言中有关指针更深层的知识. 金句分享: ✨星光…

webGL编程指南实战教程

学习路线: 如果你是在校大学生,有足够的时间去学习:前端>数学(几何线性代数)>图形学>webgl>shader >threejs>three.js源码如果你是工作中使用,需要快速出产成品:前端>thr…

【博学谷学习记录】超强总结,用心分享 | 架构师 JDK源码学习总结

文章目录HashMap类1.定义2.哈希表3.JDK1.8前HashMap的数据结构4.JDK1.8后HashMap的数据结构5.类构造器6.字段属性①Node<K,V>[] table②size③loadFactor④threshold7.构造函数①默认无参构造函数②指定初始容量的构造函数8.确定哈希桶数组索引位置9.添加元素10.扩容机制…

操作系统重难点笔记

1.信号量机制&#xff0c;读者/写者问题 读者/写者问题分为两种情况&#xff1a; 1.读者和写者互斥&#xff0c;并且不同的读者和写者之间都互斥,一共三个互斥 下面给出伪代码 int m1; int mr1; int mw1; int count0; writer() {while(1){P(mw);........V(mw);} } reader() {…

防止暴力破解ssh的四种方法

一. 方法介绍 防止暴力破解的四种方法&#xff1a; 1 密码要写的足够的复杂&#xff0c;通常建议将密码写16位&#xff0c;并且无连贯的数字或者字母&#xff1b;当然也可以固定一个时间修改一次密码&#xff0c;推荐是一个月修改一次会稳妥一些2 修改ssh的端口号&#xff0c;…

【剧前爆米花--爪哇岛寻宝】MySQL中索引和事务

作者&#xff1a;困了电视剧 专栏&#xff1a;《MySQL数据库》 文章分布&#xff1a;这是一篇关于Java中异常类的文章&#xff0c;在本篇文章中详细讲解了异常的使用逻辑和底层的执行过程&#xff0c;如有疏漏&#xff0c;欢迎大佬指正&#xff01; 目录 索引 用法 底层逻辑…

中医药NER命名实体识别基于SPANNER方式

一个不知名大学生&#xff0c;江湖人称菜狗 original author: Jacky Li Email : 3435673055qq.com Time of completion&#xff1a;2023.3.5 Last edited: 2023.3.5 导读 本文使用SPANNER方式实现对中医药进行实体识别&#xff0c;采用focal loss 进行优化。 本文章作用防止安静…

【微信小程序】计算器案例

&#x1f3c6;今日学习目标&#xff1a;第二十一期——计算器案例 ✨个人主页&#xff1a;颜颜yan_的个人主页 ⏰预计时间&#xff1a;30分钟 &#x1f389;专栏系列&#xff1a;我的第一个微信小程序 计算器前言实现效果实现步骤wxmlwxssjs数字按钮事件处理函数计算按钮处理事…

为啥一个 main 方法就能启动项目

在 Spring Boot 出现之前&#xff0c;我们要运行一个 Java Web 应用&#xff0c;首先需要有一个 Web 容器&#xff08;例如 Tomcat 或 Jetty&#xff09;&#xff0c;然后将我们的 Web 应用打包后放到容器的相应目录下&#xff0c;最后再启动容器。 在 IDE 中也需要对 Web 容器…

【WEB前端进阶之路】 HTML 全路线学习知识点梳理(中)

前言 本文是HTML零基础学习系列的第二篇文章&#xff0c;点此阅读 上一篇文章。 文章目录前言六.HTML标题1.HTML标题2.HTML水平线3.HTML 注释七.HTML段落1.HTML段落2.HTML换行八.HTML文本格式化九.HTML链接十.HTML头部十一.HTML图像十二.HTML表格十三.HTML列表十四.HTML区块1.H…

C#:Krypton控件使用方法详解(第十二讲) ——kryptonCheckButton

今天介绍的Krypton控件中的kryptonCheckButton。下面先介绍外观属性&#xff1a;Checked属性&#xff1a;表示控件是否处于已启用状态&#xff0c;属性值为Bool类型&#xff0c;属性值为true时&#xff0c;表示控件处于已选中状态。属性值为false时&#xff0c;表示控件处于不选…

黄河流域公安院校网络空间安全技能挑战赛 QAQ 题解

目录 一.获取pyc文件 二.反编译出.py源码 三.程序逻辑 1.第一个限制条件 2.第二段 3.第三段 这题是对python打包成的可执行程序逆向 如果对如何反编译.pyc和.py文件有疑问可以参考: Python逆向基本操作步骤——以杭电新生赛hgame week2 reverse stream(python3.10逆向)…

IOC(概念和原理)

文章目录1. IOC容器概念2. IOC底层原理3. IOC&#xff08;接口&#xff09;4. IOC操作Bean管理&#xff08;概念&#xff09;5. IOC操作Bean管理&#xff08;基于xml方式&#xff09;5.1 基于xml创建对象5.2 基于xml方式注入属性5.2.1 DI&#xff1a;依赖注入&#xff0c;就是注…