【Java】接口详解
接口是抽象类的更进一步. 抽象类中还可以包含非抽象方法, 和字段. 而接口中包含的方法都是抽象方法, 字段只能包含静态常量。
一个简单的接口代码示例
interface IShape {
void draw();
}
class Cycle implements IShape {
@Override
public void draw() {
System.out.println("○");
}
}
public class Data {
public static void main(String[] args) {
IShape shape = new Rect();
shape.draw();
}
}
定义接口的注意事项:
- 使用 interface 定义一个接口
- 接口中的方法一定是抽象方法, 因此可以省略 abstract
- 接口中的方法一定是 public, 因此可以省略 public
- Cycle 使用 implements 继承接口. 此时表达的含义不再是 "扩展", 而是 "实现"
- 在调用的时候同样可以创建一个接口的引用, 对应到一个子类的实例.
- 接口不能单独被实例化
定义一个完整的接口是这样的:
interface Ishape{
public static final int num = 10;
public abstruct void draw();
}
但是严格来说我们在定义一个接口的时候通常会省略 public static final 和 public abstruct ,在我们定义接口的时候里面的变量和方法会自动加上。
省略之后的写法:
interface Ishape{
int num = 10;
void draw();
}
实现多个接口
有的时候我们需要让一个类同时继承自多个父类. 这件事情在有些编程语言通过 多继承 的方式来实现的.然而 Java 中只支持单继承, 一个类只能 extends 一个父类. 但是可以同时实现多个接口, 也能达到多继承类似的效果。
代码示例:
interface Ifly{void fly();
}
interface Irunning{void running();
}
interface Iswimming{void swimming();
}
abstract class Animal{public String name;public int age;public Animal(String name,int age){this.name = name;this.age = age;}abstract public void eat();
}
class Dog extends Animal implements Iswimming , Irunning{public Dog(String name,int age){super(name,age);}@Overridepublic void running() {System.out.println(this.name + "正在跑");}@Overridepublic void swimming() {System.out.println(this.name + "正在游泳");}@Overridepublic void eat() {System.out.println(this.name + "正在吃狗粮");}
}public class Data{public static void test1(Animal animal){animal.eat();}public static void test2(Ifly ifly){ifly.fly();}public static void test3(Iswimming iswimming){iswimming.swimming();}public static void test4(Irunning irunning){irunning.running();}public static void main(String[] args) {test1(new Dog("小黄" ,20));test3(new Dog("小黄" ,20));test4(new Dog("小黄" ,20));}
}
上面的代码展示了 Java 面向对象编程中最常见的用法: 一个类继承一个父类, 同时实现多种接口。
在这个代码中我们定义了三个接口:Ifly 、Irunning 、Iswimming 。一个抽象类:Animal 。然后定义了一个类来继承这个抽象类并且实现了两个接口。
上述代码运行结果:
接口的常见使用案例
Comparable接口
给对象数组排序
代码示例:
class Student implements Comparable<Student>{private String name;private int score;public Student(String name, int score) {this.name = name;this.score = score;}@Overridepublic String toString() {return "[" + this.name + ":" + this.score + "]";}@Overridepublic int compareTo(Student o) {return this.score - o.score;}
}
public class Data{public static void main(String[] args) {Student[] student = {new Student("小明",87),new Student("小黄",94),new Student("小李",89)};Arrays.sort(student);System.out.println(Arrays.toString(student));}
}
在这个代码中我们定义了一个 Student 类:
class Student {
private String name;
private int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "[" + this.name + ":" + this.score + "]";
}
}
然后用这个类创建了一个数组:
Student[] student = {new Student("小明",87),new Student("小黄",94),new Student("小李",89)};
接着我们给 Student 类实现接口 Comparable<Student> ,这样我们就可以给该类实例化的成员进行比较大小。
上述代码的运行结果:
注意事项: 对于 sort 方法来说, 需要传入的数组的每个对象都是 "可比较" 的, 需要具备 compareTo 这样的能力. 通过重写 compareTo 方法的方式, 就可以定义比较规则。
Comparator接口
另外一种比较一个类的两个实例的方法:
代码示例:
class Person implements Comparable<Person>{public String name;public int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic int compareTo(Person o) {return this.age - o.age;}
}
class AgeComparator implements Comparator<Person>{@Overridepublic int compare(Person o1, Person o2) {return o1.age - o2.age;}
}
class NameComparator implements Comparator<Person>{@Overridepublic int compare(Person o1, Person o2) {return o1.name.compareTo(o2.name);}
}
public class Data{public static void main(String[] args) {Person p1 = new Person("小明",20);Person p2 = new Person("小黄",30);System.out.println(p1.compareTo(p2));AgeComparator agecomparator = new AgeComparator();System.out.println(agecomparator.compare(p1,p2));NameComparator namecomparator = new NameComparator();namecomparator.compare(p1,p2);}
}
在这个代码中我们为了进行比较,额外创建了一个类来实现 Comparator 接口并且在该类里面重写 compare 方法。
Clonable 接口
浅拷贝 VS 深拷贝
浅拷贝示例
代码示例:
class Person implements Cloneable{public int age;public Person(int age) {this.age = age;}@Overridepublic String toString() {return "Person{" +"age=" + age +'}';}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
public class Data{public static void main(String[] args) throws CloneNotSupportedException {Person p1 = new Person(20);Person p2 = (Person)p1.clone();System.out.println(p1);System.out.println(p2);}
}
这里我们定义了一个类 Person 并且实现了接口 Cloneable 重写了方法 clone 。在测试类中我们将 p1 里面的内容拷贝到了 p2 里面。
代码运行结果:
接着我们再定义一个 Money 类:
class Money{public double money = 19.9; }
并且在 Person 类中使用这个类:
class Person implements Cloneable{public int age;public Money m = new Money();public Person(int age) {this.age = age;}@Overridepublic String toString() {return "Person{" +"age=" + age +'}';}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();} }
接着我们再进行拷贝,将 p1 里面的内容拷贝到 p2 里面,然后我们改变 p2 里面的内容,并且将其输出:
很快我们就能看出一个问题:改变 p2 里面的内容,而 p1 里面的内容也跟着改变了呢?
接着我们引入深拷贝的理念:
深拷贝示例
代码示例:
class Money implements Cloneable{public double money = 19.9;@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
class Person implements Cloneable{public int age;public Money m = new Money();public Person(int age) {this.age = age;}@Overridepublic String toString() {return "Person{" +"age=" + age +'}';}@Overrideprotected Object clone() throws CloneNotSupportedException {Person tmp = (Person)super.clone();tmp.m = (Money)this.m.clone();return tmp;}
}
public class Data{public static void main(String[] args) throws CloneNotSupportedException {Person p1 = new Person(20);Person p2 = (Person)p1.clone();System.out.println(p1.m.money);System.out.println(p2.m.money);p2.m.money = 99.9;System.out.println(p1.m.money);System.out.println(p2.m.money);}
}
运行结果:
我们发现我们刚刚提出的问题被解决了。
这里我们改变了两个地方:
1、 将 Money 类也实现 Clonable 接口重写 clone 方法,将其具备能被拷贝的能力。
class Money implements Cloneable{public double money = 19.9;@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();} }
2、重写 Person 类里面的 clone 方法。
protected Object clone() throws CloneNotSupportedException {Person tmp = (Person)super.clone();tmp.m = (Money)this.m.clone();return tmp; }
接口间的继承
接口可以继承一个接口, 达到复用的效果. 使用 extends 关键字。
interface IRunning {void run();
}
interface ISwimming {void swim();
}
interface IAmphibious extends IRunning, ISwimming {void eat();
}
接口间的继承相当于把多个接口合并在一起。这里我们定义接口 Iamphibious 来继承了接口 IRunning 和接口 ISwimming 。这样该接口就有了另外两个接口里面的抽象方法,并且该接口也可以定义另外的抽象方法。
总结
抽象类与接口的区别:
核心区别: 抽象类中可以包含普通方法和普通字段, 这样的普通方法和字段可以被子类直接使用(不必重写), 而接口中不能包含普通方法, 子类必须重写所有的抽象方法。
相关文章:

【Java】接口详解
接口是抽象类的更进一步. 抽象类中还可以包含非抽象方法, 和字段. 而接口中包含的方法都是抽象方法, 字段只能包含静态常量。 一个简单的接口代码示例 interface IShape { void draw(); } class Cycle implements IShape { Override public void draw() { System.out.println…...

去掉el-table表头右侧类名是gutter,width=17px的空白区域(包括表头样式及表格奇偶行样式和表格自动滚动)
代码如下: <el-table:data"tableData"ref"scroll_Table":header-cell-style"getRowClass":cell-style"styleBack"height"350px"style"width: 100%"><el-table-column prop"id" l…...

3079. 求出加密整数的和
给你一个整数数组 nums ,数组中的元素都是 正 整数。定义一个加密函数 encrypt ,encrypt(x) 将一个整数 x 中 每一个 数位都用 x 中的 最大 数位替换。比方说 encrypt(523) 555 且 encrypt(213) 333 。 请你返回数组中所有元素加密后的 和 。 示例 1&…...

奶茶店、女装店、餐饮店是高危创业方向,原因如下:
关注卢松松,会经常给你分享一些我的经验和观点。 现在的俊男靓女们,心中都有一个执念: (1)想证明自己了,开个奶茶去…… (2)想多赚点钱了,加盟餐饮店去…… (3)工作不顺心了,搞个女装店去…… 但凡抱着…...

嵌入式笔试面试刷题(day16)
文章目录 前言一、PWM波形的占空比计算公式是什么?二、ADC和DAC在嵌入式系统中的应用场景有哪些?三、watchdog定时器的作用及其在系统中的使用是什么?四、JTAG接口在嵌入式开发中的作用是什么?五、实时操作系统(RTOS)的任务调度策…...

【MyBatis】MyBatis操作数据库(二):动态SQL、#{}与${}的区别
目录 一、 动态SQL1.1 \<if>标签1.2 \<trim>标签1.3 \<where>标签1.4 \<set>标签1.5 \<foreach>标签1.6 \<include>标签 二、 #{}与${}的区别2.1 #{}是预编译sql,${}是即时sql2.2 SQL注入2.3 #{}性能高于${}2.4 ${}用于排序功能…...

[Zer0pts2020]easy strcmp 分析与加法
查壳 Ubuntu上的64位程序 第一步应该尝试运行一下 啥也不是 (这里我改了程序,原来应该是a1>1) 但是我动调发现a1值是1 我就改了判断 但是还是没什么用 也找不到a2的引用 找一下有没有什么improt调用 发现还是啥也不是 思路这里断了 刚好这个程序几个代码而已 函数看…...

力扣7. 整数反转
给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。 如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。 假设环境不允许存储 64 位整数(有符号或无符号)。 示例 1: 输…...

Mac/Linux getline 无法读取文件内容(读取内容无法显示)
如下面代码 #include <iostream> #include <fstream>using namespace std;int main() {string file_name "1.txt";std::ifstream file(file_name);if (file.is_open()) {std::string line;while (std::getline(file, line)) {char c line.back();cout…...

NBM 算法【python,算法,机器学习】
朴素贝叶斯法(Naive Bayes model)是基于贝叶斯定理与特征条件独立假设的分类方法。 贝叶斯定理 P ( A ∣ B ) P ( B ∣ A ) ∗ P ( A ) P ( B ) P(A|B)\frac{P(B|A) * P(A)}{P(B)} P(A∣B)P(B)P(B∣A)∗P(A) 其中A表示分类,B表示属性&…...

spark3.0.1版本查询Hbase数据库例子
需求背景 现有需求,需要采用spark查询hbase数据库的数据同步到中间分析库,记录spark集成hbase的简单例子代码 import org.apache.hadoop.hbase.HBaseConfiguration import org.apache.hadoop.hbase.client.{ConnectionFactory, Scan} import org.apach…...

android高效读图方式——Hardwarebuffer读图
安卓上有许许多多使用OpenGL来渲染的原因,比方说做特效/动画/硬解/人脸识别等等。渲染完成后如何从gpu中把数据快速读取出来也是高效图像处理中的重要的一环。 相对于glReadPixel的同步读取方式,安卓GLES3.0提供了更高效快速的Hardwarebuffer读图方式&a…...

悉数六大设计原则
悉数六大设计原则 目录 悉数六大设计原则前言☕谁发明了设计模式设计原则设计原则与设计模式的关系 单一职责什么是单一职责不遵循单一职责原则的设计遵循单一职责原则的设计单一职责的优点示例代码: 里氏替换原则什么是里氏替换原则示例代码:违反里氏替…...

hdfs复习
一.hadoop概述 1.4高(优势) 1).高可靠性:hadoop底层多个数据副本,即使某个计算节点存储出现故障,不会导致数据丢失。 2).高扩展性:可以动态增加服务器节点。 3).高效…...

css-Ant-Menu 导航菜单更改为左侧列表行选中
1.Ant-Menu导航菜单 导航菜单是一个网站的灵魂,用户依赖导航在各个页面中进行跳转。一般分为顶部导航和侧边导航,顶部导航提供全局性的类目和功能,侧边导航提供多级结构来收纳和排列网站架构。 2.具体代码 html <!-- 左侧切换 --><…...

02-CSS3基本样式
目录 1. CSS3简介 1.1 CSS3的兼容情况 1.2 优雅降级和渐进增强的开发思想 2. 新增选择器 2.1 选择相邻兄弟 2.2 匹配选择器 2.3 属性选择器(重点) 2.4 结构性伪类选择器(重点) 2.4.1 整体结构类型 2.4.2 标签结构类型 2.4.3 指定子元素的序号&…...

USART串口外设
USART介绍 USART:另外我们经常还会遇到串口,叫UART,少了个S,就是通用异步收发器,一般我们串口很少使用这个同步功能,所以USART和UART使用起来,也没有什么区别。 其实这个STM32的USART同步模式&a…...

大模型应用之基于Langchain的测试用例生成
一 用例生成实践效果 在组内的日常工作安排中,持续优化测试技术、提高测试效率始终是重点任务。近期,我们在探索实践使用大模型生成测试用例,期望能够借助其强大的自然语言处理能力,自动化地生成更全面和高质量的测试用例。 当前…...

C++之map
1、标准库的map类型 2、插入数据 #include <map> #include <string> #include <iostream>using namespace std;int main() {map<string, int> mapTest;// 插入到map容器内部的元素是默认按照key从小到大来排序// key类型一定要重载小于号<运算符map…...

【量算分析工具-方位角】GeoServer改造Springboot番外系列六
【量算分析工具-概述】GeoServer改造Springboot番外系列三-CSDN博客 【量算分析工具-水平距离】GeoServer改造Springboot番外系列四-CSDN博客 【量算分析工具-水平面积】GeoServer改造Springboot番外系列五-CSDN博客 【量算分析工具-方位角】GeoServer改造Springboot番外系列…...

【机器学习】机器学习与大模型在人工智能领域的融合应用与性能优化新探索
文章目录 引言机器学习与大模型的基本概念机器学习概述监督学习无监督学习强化学习 大模型概述GPT-3BERTResNetTransformer 机器学习与大模型的融合应用自然语言处理文本生成文本分类机器翻译 图像识别自动驾驶医学影像分析 语音识别智能助手语音转文字 大模型性能优化的新探索…...

上传图片并显示#Vue3#后端接口数据
上传图片并显示#Vue3#后端接口数据 效果: 上传并显示图片 代码: <!-- 上传图片并显示 --> <template><!-- 上传图片start --><div><el-form><el-form-item><el-uploadmultipleclass"avatar-uploader&quo…...

音视频开发14 FFmpeg 视频 相关格式分析 -- H264 NALU格式分析
H264简介-也叫做 AVC H.264,在MPEG的标准⾥是MPEG-4的⼀个组成部分–MPEG-4 Part 10,⼜叫Advanced Video Codec,因此常常称为MPEG-4 AVC或直接叫AVC。 原始数据YUV,RGB为什么要压缩-知道就行 在⾳视频传输过程中,视频⽂件的传输…...

Qt学习记录(15)数据库
目录 前言: 数据库连接 项目文件加上sql 打印查看Qt支持哪些数据库驱动 QMYSQL [static] QSqlDatabase QSqlDatabase::addDatabase(const QString &type, const QString &connectionName QLatin1String(defaultConnection)) 数据库插入 头文件.h 源…...

c++常用设计模式
1、单例模式(Singleton):保证一个类只有一个实例,提供一个全局访问点; class Singleton { private:static Singleton* instance;Singleton() {}public:static Singleton* getInstance() {if (instance nullptr) {instance new Singleton()…...

【动手学深度学习】softmax回归从零开始实现的研究详情
目录 🌊1. 研究目的 🌊2. 研究准备 🌊3. 研究内容 🌍3.1 softmax回归的从零开始实现 🌍3.2 基础练习 🌊4. 研究体会 🌊1. 研究目的 理解softmax回归的原理和基本实现方式;学习…...

MySQL:MySQL执行一条SQL查询语句的执行过程
当多个客户端同时连接到MySQL,用SQL语句去增删改查数据,针对查询场景,MySQL要保证尽可能快地返回客户端结果。 了解了这些需求场景,我们可能会对MySQL进行如下设计: 其中,连接器管理客户端的连接,负责管理连接、认证鉴权等;查询缓存则是为了加速查询,命中则直接返回结…...

解决Python导入第三方模块报错“TypeError: the first argument must be callable”
注意以下内容只对导包时遇到同样的报错会有参考价值。 问题描述 当你尝试导入第三方模块时,可能会遇到如下报错信息: TypeError: the first argument must be callable 猜测原因 经过仔细检查代码,我猜测这个错误的原因是由于变量名冲突所…...

在python中连接了数据库后想要在python中通过图形化界面显示数据库的查询结果,请问怎么实现比较好? /ttk库的treeview的使用
在Python中,你可以使用图形用户界面(GUI)库来显示数据库的查询结果。常见的GUI库包括Tkinter(Python自带)、PyQt、wxPython等。以下是一个使用Tkinter库来显示数据库查询结果的简单示例。 首先,你需要确保…...

OZON的选品工具,OZON选品工具推荐
在电商领域,选品一直是决定卖家成功与否的关键因素之一。随着OZON平台的崛起,越来越多的卖家开始关注并寻求有效的选品工具,以帮助他们在这个竞争激烈的市场中脱颖而出。本文将详细介绍OZON的选品工具,并推荐几款实用的辅助工具&a…...