一个月学会Java 第13天 抽象类与接口

news2024/10/21 9:36:32

Day13 抽象类与接口

通过了前面的学习,我们已经掌握了面向对象的基础 继承 封装 多态

第一章 抽象类

接下来,我们要对面向对象学习高级的部分,我们先要学到的就是抽象类,听名字也能想到,肯定很抽象,那我们先来学习一下抽象的单词
abstract 自然我们后面有关抽象的都是需要使用这个关键字去修饰的

首先我们先来讲一讲概念和用法,我们的抽象类的作用是包含抽象方法,就我们平时的编码过程其实方法都是直接写的对吧,没有出现过方法是单单声明的过程,我们接下来学习的这个就是可以理解为声明方法。

然后我们需要将继承声明抽象方法的这个类并实现这个被声明的这个方法,被声明的方法我们一般叫做抽象方法,需要在继承后实现他,实现就是相当于对这个方法进行初始化

最后就是我们的抽象类的定义和我们抽象方法的所去所从,有抽象方法的类必须是抽象类,抽象类可以没有抽象方法,抽象类不能被创建对象,抽象类也可以有正常的方法

我们来看看声明,首先是抽象类,就是在class面前加上
abstract,然后抽象方法则是加上abstract之后去除方法体然后在末尾加上分号,然后注意标注在方法上的abstract关键字不能与static和final共存

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

    }
}

abstract class Father {
    public abstract void p();
}

这个就是非常完美的案例,然后我们来看看创建对象能不能成功

在这里插入图片描述

很明显,直接失败了,因为抽象类不能创建对象,但是可以被继承,所以我们可以这么修改

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

    }
}

class Son extends Father {

}

abstract class Father {
    public abstract void p();
}

在这里插入图片描述

很明显报错了,这个问题是什么呢,就是我们上面所说的,抽象类可以没有抽象方法,但是抽象方法必须在抽象类里面,我们现在继承过来的是不是继承了抽象方法p,所以我们需要在里面实现了p之后才能是正常的类,或者我们把Son也变成抽象类,再让后者继承他之后再实现方法p

public class Hello {
    public static void main(String[] args) {
        Son son = new Son();
        son.p();
    }
}

class Son extends Father {
    @Override
    public void p() {
        System.out.println("I'm method p()");
    }
}

abstract class Father {
    public abstract void p();
}

在这里插入图片描述

自然我们也可以使用多态的方式进行调用这个p方法,因为我们可以说是在Father这个类里面规定了子类及其子类都必须要有p方法以及一次或者多次实现的可能

public class Hello {
    public static void main(String[] args) {
        Father son = new Son();
        System.out.println("现在是父指子的用法");
        son.p();
    }
}

class Son extends Father {
    @Override
    public void p() {
        System.out.println("I'm method p()");
    }
}

abstract class Father {
    public abstract void p();
}

在这里插入图片描述

自然我们也可以正常写其他方法,只不过没办法创建对象罢了,但是我们把方法写在抽象类中,然后有类继承他,并且我们使用多态的 父指子
用法也可以调用

public class Hello {
    public static void main(String[] args) {
        Father son = new Son();
        son.p();
        son.p123();
    }
}

class Son extends Father {
    @Override
    public void p() {
        System.out.println("I'm method p()");
    }
}

abstract class Father {
    public abstract void p();

    public void p123() {
        System.out.println("print something");
    }
}

在这里插入图片描述

第二章 接口

在上面的章节我们已经见识到了抽象类,然后在我们的代码中其实还有更抽象的东西,就是极致抽象的类,我们叫做接口

我们只需要把class这个关键字替换成interface即可,自然我们使用public
class的时候也可以把这个class换成interface,只不过里面是极致的抽象,所以不能出现正常的方法,只能有抽象方法

还有一点,我们可以只写 返回值 方法名(参数列表); 因为既然已经极致的抽象,自然会带上配合抽象的public
abstract,我们可以在idea中先试用一下,还有一件事,就是我们使用idea创建类的时候,可以看到其实我们可以选择接口进行创建的

在这里插入图片描述

我们可以看到,下面有接口的选项,其实创建完之后也就是把class换成了interface自然我们在单个文件写多个类的时候,换成接口之后也是一样的操作,只需要把class换成interface即可,但是切记,我们在开发过程中是不能这么写的,一个文件里面只能有一个类,我指的是同级类,自然不包含我们后面要说的内部类的内容

在这里插入图片描述

我们进行创建

在这里插入图片描述

我们可以看到已经完成了创建,并且自动替换为了interface,然后在左边项目列表里面的图标也发生了变化,中间的数字变成了I然后变成了绿色的图标,说明这个就是接口,因为I是interface的首字母,就和Class的蓝色填充一样,蓝色的C

小图标也是带有细节的,比如我们的Hello类里面现在应该是写着不止一个类,左边就有个小箭头,然后我们的Hello类里面有main函数,所以就有个绿色箭头代表可运行

接口中的方法声明

我们再看看,我说的在接口中写方法只能写抽象的,还有不需要写public和abstract

在这里插入图片描述

是不是提示是冗余的,就说明了可以不写这两个关键字。

接口中的属性

然后我们在接口中也是可以写属性的,只不过一写就会变成常量,而且是静态的常量,可以调用的更加的方便,如果你问抽象类中的属性呢,我只能说和普通的类是一样的,只是抽象方法是特殊的,还有对象不能创建而已,然后我们的接口既然是抽象到极致的抽象类,那么,自然他也没办法创建对象,至于属性,我马上就要说了

而且抽象到极致的类,也就是接口中也不能出现
常量声明也就是属性声明和方法声明外还有jdk8新添加的新特性default方法之外,其余在类中可以用的,在接口中都是不能用,而且接口作为规范方法的作用,在开发过程的作用是很大的,有了接口就能规定一个规范

就像我们现在使用的type-c接口一样,大部分的手机厂商都是为了满足这个接口,相当于我们使用接口作为父,然后手机作为子进行了 父指子
然后进行调用一样,充电,数据传输都使用的接口,差不多就是这个接口的意思

package interfaceUsing;

public interface TestInterface {
    //接口中的属性声明 默认自带 public static final
    String name = "tom";
    public static final String a = "a";
    //多余的就不写了
    public final String b = "b";

    //抽象方法声明,自带public abstract
    void p();
}

在这里插入图片描述

很明显,我们可以看到前面的public static final 都是灰色的,也就是是自动加上的。

接口的实现(类继承接口)

毕竟是抽象到极致的类,所以我们的接口进行继承也就是接口的实现也是和普通的类不一样的,因为接口里面规定的都是抽象方法,所以可以重复无所谓,因为我们java中是只支持单继承的,我们所有的类只能有一个爹,就不会出现我是Hello继承了Father和Father2,然后Father和Father2中的方法重复了,那我调用这同个名字的方法调用的是哪一个,但是我们的接口都是抽象的,所以可以随便继承

接口的继承就是实现,然后实现的英文单词就是implements

public class Hello {
    public static void main(String[] args) {
        Test test = new Test();
        test.p();
        System.out.println(test.sum(1, 5));
    }
}

class Test implements interface1 {

    @Override
    public void p() {
        System.out.println("method p()");
    }

    @Override
    public int sum(int a, int b) {
        return a + b;
    }
}

interface interface1 {
    void p();

    int sum(int a, int b);
}

在这里插入图片描述

接口的继承(接口继承接口)

我们类继承接口也就是类实现这个接口,使用的是implements,但是我们接口与接口还是正常的继承关系,继承这么抽象的方法,所以还是使用的extends,只有我们接口变换到了类里面才会是使用了implements
实现。

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

class Test implements interface1 {

    @Override
    public void p() {
        System.out.println("method p()");
    }

    @Override
    public int sum(int a, int b) {
        return a + b;
    }

    @Override
    public void fatherMethod() {
        System.out.println("来自fatherInterface的方法");
    }
}

interface interface1 extends interFather {
    void p();

    int sum(int a, int b);
}

interface interFather {
    void fatherMethod();
}

在这里插入图片描述

明显一看就能看出来,接口与接口之间使用的是不是还是extends

接口的jdk8新特性

如果我们使用的jdk8及以上的话,接口除了我以上说的抽象到极致的方法,写上 返回值 方法名 (参数列表) 会自动添上 public 和
abstract 与 写属性直接会变成 public static final 修饰的常量之外,还会有两个新特性

一个是默认方法,另外一个则是静态方法,自然我们不需要写public,他会自带public

package interfaceUsing;

public interface TestInterface {
    static void p() {
        System.out.println("static void p()");
    }

    default void p1() {
        System.out.println("default void p1()");
    }
}

class H implements TestInterface {

}

class Main {
    public static void main(String[] args) {
        H h = new H();
        h.p1();
        TestInterface.p();
    }
}

在这里插入图片描述

我们明显看到,默认方法其实就是普通的public方法,而静态方法就是静态的public方法,我们调用默认方法的时候需要有类去实现这个接口然后创建对象才可以调用,而静态方法和我们所理解的静态方法是一样的,我们可以使用
类名.静态方法名(参数列表);的方式进行调用,只不过从类名变成了接口名

以上差不多就是这次的全部内容了,是不是有点抽象,多写一写就习惯和熟悉起来了

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

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

相关文章

电力电子技术(二)

三相可控整流电路:(主要包括三相半波和三相桥式) (一)三相半波: (1.1电阻性负载) 右侧第三个图代表VT1晶闸管的流经电流波形,一个周期仅导通一次:晶闸管导…

Netty讲解与案例

1.Netty简介: 官网:https://netty.io/ Netty 是一个 NIO 客户端服务器框架,可以快速轻松地开发协议服务器和客户端等网络应用程序。它极大地简化和精简了 TCP 和 UDP 套接字服务器等网络编程。 “快速简便”并不意味着最终的应用程序会存在…

Halcon 使用二维像素分类对图像进行分割

文章目录 算子histo_2dim 计算双通道灰度值图像的直方图class_2dim_sup 使用二维像素分类对图像进行分割 示例 算子 histo_2dim 计算双通道灰度值图像的直方图 histo_2dim(Regions, ImageCol, ImageRow : Histo2Dim : : )Regions (输入对象):在此区域内计算直方图…

腾讯云视立方开通各项云服务相关

云直播 如何开通云直播服务? 进入 云直播管理控制台,进入腾讯云直播服务开通页,查看相关协议并勾选同意,单击申请开通即可开通云直播服务。 。 如何开启流防盗链 KEY? 推流防盗链 KEY 是为了确保只有您的 App 用户…

dockerfile 用法全解析

FROM 构建基于alpine的镜像,单条执行就是复制了一个apline镜像(除了FROM其他都是非必须的) WORKDIR 是之指定接下来的shell语句是运行在哪个路径下,没有就会创建目录 COPY 将宿主机指定目录的文件拷贝到镜像指定目录 (ADD 源地址还可以url…

[LeetCode] 662. 二叉树最大宽度

题目描述: 给你一棵二叉树的根节点 root ,返回树的 最大宽度 。 树的 最大宽度 是所有层中最大的 宽度 。 每一层的 宽度 被定义为该层最左和最右的非空节点(即,两个端点)之间的长度。将这个二叉树视作与满二叉树结…

【C语言刷力扣】2206.将数组划分成相等数对

题目: 解题思路: 题目中要求元素成数对出现,即每个元素出现偶数次。用哈希表存放每个数出现的次数,再循环查看每个数的次数是否位偶数。 typedef struct {int key;int count;UT_hash_handle hh; } hashEntry;bool divideArray(int…

IDEA下载安装

文章目录 1、下载安装包2、安装IDEA3、全局配置4、安装插件 1、下载安装包 IDEA官网下载最新IDEA。 上面的ULtimate是旗舰版,试用30天,之后是需要收费的,下面黑色区域的Community是社区版,功能不如旗舰版丰富,但是好在…

文件的二维码怎么做成?简单的3步生成二维码技巧

数字化时代的到来,用来将内容分享给其他人展示的方式也越来越多。其中二维码就是现在很流行的一种方式,将内容存入二维码后,其他人就可以扫描分享二维码来查看内容,那么文件生成二维码该怎么操作呢? 通过使用文件二维…

如何轻松实现Patreon订阅,获得独家内容

目录 1. 什么是Patreon? Patreon是一个非常流行的在线平台。 它支持内容创作者通过订阅的方式,直接从粉丝那里获取资金支持。无论是艺术家、音乐家,还是作家、视频制作人,都能在这里找到自己的粉丝群体。 简而言之,你可以通过订阅他们定期发布的独家内容,享受到更…

量子噪声与量子操作

由于量子不确定性和量子态的测量过程而引入的随机波动,量子噪声不可避免。 经典噪声 想象一下,一个比特存储在硬盘驱动器上, 它与普通计算机相连,该比特从状态0或1开始,经过长时间,散乱的磁场很可能会导致…

020 elasticsearch7.10.2 elasticsearch-head kibana安装

文章目录 全文检索流程ElasticSearch介绍ElasticSearch应用场景elasticsearch安装允许远程访问设置vm.max_map_count 的值 elasticsearch-head允许跨域 kibana 商品数量超千万,数据库无法使用索引 如何使用全文检索: 使用lucene,在java中唯一…

AI视频监控卫士:一键Docker简易安装,开源技术引领视频监控

AI视频监控卫士的主要应用场景: 我们决定开源的原因: 1. 灵活性与可定制性: 开源产品的代码对用户公开,允许开发者根据特定需求进行自定义和扩展。思通数科AI视频监控卫士作为开源项目,可以灵活适应不同企业或项目的需…

一些NLP代表性模型

(一)BERT 由Bidirectional Encoder Representations from Transformers的首字母组成,是encoder-only结构类型的代表。 模型分预训练和微调两步,预训练任务有两类:masked language model(MLM)、next sentence predict…

我作为TypeScript开发人员是如何学习Rust的

讲讲我作为TypeScript开发人员学习Rust的经验吧,希望对你有帮助 像许多开发人员一样,我通过专注于网络技术开始了我的编程生涯。我相信这是一个很好的起点,JavaScript,互联网的语言,以及许多,是一个令人难…

Axure原型设计秘籍:解锁高效设计与开发的宝藏工具

​ 在快速迭代的数字时代,原型设计成为了产品开发与用户体验优化的关键环节。Axure,作为一款备受推崇的原型设计工具,凭借其强大的功能、直观的界面和丰富的资源,成为了设计师和产品经理们的得力助手。本文将带你深入探索Axure的原…

JavaScript中的对象,常用内置对象和数据类型

一、对象 1.概念 什么是对象? 在JavaScript中,对象是一组无序的相关属性和方法集合,所有的事物都是对象,例如:字符串、数值、数组和函数等等。 对象是由属性和方法组成的。 属性:事物的特征,在…

使用CSS Flexbox创建简洁时间轴

使用CSS Flexbox创建简洁时间轴 在网页设计中,时间轴是一种常见且有效的方式来展示事件的顺序和进程。本文将介绍如何使用CSS Flexbox创建一个简洁优雅的时间轴,无需复杂的JavaScript代码。 基本HTML结构 首先,我们需要创建基本的HTML结构: html复制<div class"ti…

《CUDA编程》8.共享内存的合理使用

共享内存是 一种可被程序员直接操控的缓存&#xff0c;主要作用有两个&#xff1a; ①减少核函数中对全局内存的访 问次数&#xff0c;实现高效的线程块内部的通信 ②提高全局内存访问的合并度 将通过两个具体的例子阐明共享内存的合理使用&#xff0c;一个数组归约的例子和讨矩…