[Java入门]抽象类和接口

[Java入门]抽象类和接口

  • 1. 抽象类
    • 1.1 抽象类的概念
    • 1.2 抽象类语法
    • 1.3 抽象类特性
    • 1.4 抽象类的作用
  • 2. 接口
    • 2.1 接口的概念
    • 2.2 语法规则
    • 2.3 接口使用
    • 2.4 接口特性
    • 2.5 实现多个接口
    • 2.6 接口间的继承
    • 2.7 抽象类和接口的区别
  • 3. Object类
    • 3.1 获取对象信息
    • 3.2 对象比较equals方法

1. 抽象类

1.1 抽象类的概念

在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。 比如:

在这里插入图片描述
【说明】

  • 从图中可知,矩形类、圆形类、三角形类都属于图形类,所以三者都与Shape类是继承关系
  • 由于Shape不是具体的图形,该类虽然存在draw方法,但无法画出具体图形,即draw方法无法具体实现
  • 因此Shape类中没有足够的信息来描绘自己的对象,所以Shape类就能被设计为抽象类

在这里插入图片描述

【说明】

  • 再来看这个图,很明显可以看出Student类、Teacher类、Waiter类都与Person类是继承关系
  • 由于Person不是具体的人,所以无法确定职业,即使它存在career方法,那也无法具体的实现该方法
  • 因此Person类中没有足够的信息来描绘自己的对象,career方法也无法具体的实现,所以该类就可以被设计为抽象类

从上面两个例子中,两个父类Shape类和Person类 的 draw方法和career方法是无法具体实现的,只有它们的子类才会有具体的实现,像这种没有具体实现的方法,通常设计为抽象方法(abstract method),而包含抽象方法的类称为 抽象类(abstract class)

1.2 抽象类语法

在Java中,如果一个类被 abstract 修饰,那么这个类被称为抽象类,而在抽象类中,存在被 abstract 修饰的方法,那么这个方法就被称为 抽象方法。

//抽象类: 在普通类前用 abstract 修饰
//抽象类也是类 也可以定义成员变量 和 方法
public abstract class Person {public String name;public int age;public void chat(){System.out.println("在聊天!");}//抽象方法:在普通方法前用 abstract 修饰//抽象方法 可以没有方法体public abstract void career();
}

注意:抽象类也是类,内部可以包含普通方法和属性,甚至构造方法

1.3 抽象类特性

  1. 抽象类被 abstract 修饰
  2. 抽象类跟普通类一样,也可以包含普通方法和属性,还有构造方法
  3. 抽象方法被 abstract 修饰,且必须在抽象类中
  4. 抽象方法不能被 final 和 static 修饰,因为要被重写
  5. private 和 abstract 不能同时存在
看报错提示:private abstract void career();//Illegal combination of modifiers: 'abstract' and 'private'public static abstract void career();//Illegal combination of modifiers: 'abstract' and 'static'public final abstract void career();//Illegal combination of modifiers: 'final' and 'abstract'
  1. 抽象类被设计出来就是为了被继承
  2. 普通类继承抽象类 必须重写抽象类中所有的抽象方法,否则就将普通类改为抽象类
abstract class Person {public abstract void career();
}class Student extends Person{//@Overridepublic void career() {System.out.println("我的职业是学生!");}
}
  1. 当普通类B不想重写时,就将普通类B变成抽象类B,那么当普通类C想继承抽象类B时,必须要重写抽象类B 和 抽象类A 的所有抽象方法
abstract class Person {public abstract void career();
}public abstract class Student extends Person{@Overridepublic abstract void career();public abstract void homework();
}class StudentOfPrimary extends Student{@Overridepublic void career() {System.out.println("我是小学生!");}@Overridepublic void homework() {System.out.println("我在写小学生作业!");}
}
  1. 抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类
  2. 抽象类中可以有构造方法,供子类创建对象时,初始化父类的成员变量

1.4 抽象类的作用

抽象类本身不能被实例化, 要想使用, 只能创建该抽象类的子类. 然后让子类重写抽象类中的抽象方法.

有些同学可能会说了, 普通的类也可以被继承呀, 普通的方法也可以被重写呀, 为啥非得用抽象类和抽象方法呢?

确实如此. 但是使用抽象类相当于多了一重编译器的校验.

使用抽象类的场景就如上面的代码, 实际工作不应该由父类完成, 而应由子类完成. 那么此时如果不小心误用成父类了, 使用普通类编译器是不会报错的. 但是父类是抽象类就会在实例化的时候提示错误, 让我们尽早发现问题.

很多语法存在的意义都是为了 “预防出错”, 例如我们曾经用过的 final 也是类似. 创建的变量用户不去修改, 不就相当于常量嘛? 但是加上 final 能够在不小心误修改的时候, 让编译器及时提醒我们.

充分利用编译器的校验, 在实际开发中是非常有意义的.

2. 接口

2.1 接口的概念

接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用。在Java中,接口可以看成是:多个类的公共规范,是一种引用数据类型

2.2 语法规则

接口的定义格式与定义类的格式基本相同,将class关键字换成 interface 关键字,就定义了一个接口。

public interface Drawable {public static final int a = 0;//接口中定义变量时 public static final 是固定存在的 可以不写public abstract void draw();//接口中定义方法时 public abstract 是固定存在的 可以不写
}

注意:接口中的方法都是抽象方法

提示:

  1. 创建接口时, 接口的命名一般以大写字母 I 开头.
  2. 接口的命名一般使用 “形容词” 词性的单词.
  3. 阿里编码规范中约定, 接口中的方法和属性不要加任何修饰符号, 保持代码的简洁性.

2.3 接口使用

接口不能直接使用,必须要有一个"实现类"来"实现"该接口,实现接口中的所有抽象方法。 模板:

public class 类名 implements 接口名{
}

比如:

public interface Drawable {public abstract void draw();
}public abstract class Shape {public abstract void getArea();
}public class Circle extends Shape implements Drawable{@Overridepublic void getArea() {System.out.println("圆的面积");}@Overridepublic void draw() {System.out.println("圆");}
}public class Main {public static void main(String[] args) {Circle circle = new Circle();circle.getArea();circle.draw();}
}

2.4 接口特性

  1. 接口中定义变量时 public static final 是固定存在的 可以不写
  2. 接口中定义方法时 public abstract 是固定存在的 可以不写
  3. 接口中的方法都是抽象方法
  4. 接口中的方法不能在接口中实现,只能在实现该接口的类中实现
  5. 若接口中的方法被static修饰,那么可以在接口中有具体的实现
public interface Drawable {public static final int a = 0;public abstract void draw();static void draw1(){System.out.println("画画");}
}
//Circle类 实现 Drawable接口
public class Circle implements Drawable{@Overridepublic void draw() {System.out.println("圆");}
}
  1. 接口是引用类型,但不能通过 new 来实例化
Drawable drawable = new Drawable();
报错:'Drawable' is abstract; cannot be instantiated
  1. 在重写接口中的方法时,必须加上public
  2. 接口中不能有构造方法和代码块

2.5 实现多个接口

在Java中,类和类之间是单继承的,一个类只能有一个父类,即Java中不支持多继承,但是一个类可以实现多个接口。举例说明:

一个动物类
public abstract class Animal {private String name;private int age;public Animal(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public int getAge() {return age;}public abstract void makeSound();
}两个接口
public interface Swimming {public void swim();
}public interface Trainbale {public void train();
}两个子类:
猫
public class Cat extends Animal implements Trainbale{public Cat(String name, int age) {super(name, age);}@Overridepublic void makeSound() {System.out.println(getName() + "喵喵喵!");}@Overridepublic void train() {System.out.println(getName() + "可被训练!");}
}狗(实现了两个接口)
public class Dog extends Animal implements Trainbale,Swimming{public Dog(String name, int age) {super(name, age);}@Overridepublic void makeSound() {System.out.println(getName() + "旺旺旺");}@Overridepublic void train() {System.out.println(getName() + "可被训练!");}@Overridepublic void swim() {System.out.println(getName() + "会游泳!");}
}

从代码可以看出,子类狗继承了Animal类实现了两个接口,这是根据它的特性实现的。这是Java中最常见的的用法:一个类继承一个父类实现多个接口

继承表达的含义是 is - a 语义, 而接口表达的含义是 具有 xxx 特性 .

  • 猫是一种动物,具有可被训练的特性.
  • 狗是一种动物,具有会游泳、可被训练的特性.

这样设计有什么好处呢? 时刻牢记多态的好处, 让程序猿忘记类型. 有了接口之后, 类的使用者就不必关注具体类型,而只关注某个类是否具备某种能力.

2.6 接口间的继承

在Java中,类与类之间可以继承,类与接口之间可以实现,那接口与接口之间呢?是可以继承的,且可以多继承,可以借助接口达到多继承的目的!

public interface Flying {public void fly();
}
public interface Trainbale {public void train();
}
//接口与接口之间也是通过 extends 继承,并非用 implements
//若继承的接口中已写有方法,那么本接口可以不用添加特有方法
public interface Merge extends Flying,Trainbale{
}//Bird类 实现了 Merge接口 那么就要重写train、fly方法
public class Bird implements Merge{@Overridepublic void train() {System.out.println("可被训练!");}@Overridepublic void fly() {System.out.println("会飞!");}
}

接口之间的继承相当于把多个接口合并起来。

2.7 抽象类和接口的区别

抽象类和接口都是 Java 中多态的常见使用方式. 都需要重点掌握. 同时又要认清两者的区别(重要!!! 常见面试题).

核心区别: 抽象类中可以包含普通方法和普通字段, 这样的普通方法和字段可以被子类直接使用(不必重写), 而接口中不能包含普通方法, 子类必须重写所有的抽象方法.

抽象类存在的意义是为了让编译器更好的校验, 像 前面提到的Animal、Shape等 这样的类我们并不会直接使用, 而是使用它的子类.万一不小心创建了 Animal 或 Shape的实例, 编译器会及时提醒我们.

在这里插入图片描述

3. Object类

Object是Java默认提供的一个类。Java里面除了Object类,所有的类都是存在继承关系的。默认会继承Object父类。即所有类的对象(无论是Java自带的还是自己设计创建的)都可以使用Object的引用进行接收。

public class A {
}public class Test {public static void main(String[] args) {A a = new A(); //自己设计的类String str = new String("123");//Java中已存在的类func(a);func(str);}
public static void func(Object o){System.out.println(o);}
}//打印结果
demo5.A@119d7047
123

所以在开发之中,Object类是参数的最高统一类型。

但是Object类也存在一些定义好的方法。如下:

在这里插入图片描述
对于 Object 类中已存在的所有方法都需要熟悉掌握。
我们先来熟悉 toString()、 equals() 两个方法

3.1 获取对象信息

如果要打印对象中的内容,可以直接重写Object类中的toString()方法,内容可以根据自己的要求修改。

这是Object类中的toString()方法具体内容,可以看出是默认打印地址
在这里插入图片描述

3.2 对象比较equals方法

在Java中,== 进行比较时:
a.如果 == 左右两侧是基本类型变量,比较的是变量中值是否相同
b.如果 == 左右两侧是引用类型变量,比较的是引用变量地址是否相同
c.如果要比较对象中内容,必须重写Object中的equals方法,因为equals方法默认也是按照地址比较的:

在这里插入图片描述

class Person{private String name ;private int age ;public Person(String name, int age) {this.age = age ;this.name = name ;}
}public class Test {public static void main(String[] args) {Person p1 = new Person("gaobo", 20) ;Person p2 = new Person("gaobo", 20) ;int a = 10;int b = 10;System.out.println(a == b); // 输出trueSystem.out.println(p1 == p2); // 输出false 因为是两个对象,是两个不同的地址System.out.println(p1.equals(p2)); // 输出false}
}

未重写的equals() 方法的内容就是 比较两对象地址是否相同。

把Person类的equals方法重写后,然后比较:

class Person{private String name ;private int age ;public Person(String name, int age) {this.age = age ;this.name = name ;}public boolean equals(Object obj) {if (obj == null) {return false ;}if(this == obj) {return true ;}// 若不是Person类对象 返回 falseif (!(obj instanceof Person)) {return false ;}Person person = (Person) obj ; // 向下转型,比较属性值return this.name.equals(person.name) && this.age==person.age ;}
}//结果
System.out.println(a == b); // 输出true
System.out.println(p1 == p2); // 输出false 
System.out.println(p1.equals(p2)); // 输出true

结论:比较对象中内容是否相同的时候,一定要重写equals方法。

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

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

相关文章

聚焦数字中国|AI赋能与安全守护:Coremail引领邮件办公智能化转型

4月28日,第八届数字中国建设峰会在福州拉开序幕。当天,数字中国新产品新技术发布会开讲,Coremail受邀亮相现场,与与会嘉宾分享AI在邮件产品领域的最新应用成果和实践经验。 Coremail首席客户代表刘子建以《AI赋能与安全守护&#…

Qt官方案例知识点总结(拖放操作——Drag And Drop Robot )

-------------------------------------------------------------------------------------------------------------------------------- QPixmap轮廓剪裁 去掉Pixmap的外围部分,如下: QPixmap pixmap("./img"); //调用createHeuristicMas…

【LLM】MOE混合专家大模型综述(重要模块原理)

note 当前的 MoE 架构就是一个用显存换训练时长/推理延迟的架构MoE 目前的架构基本集中在于将原先 GPT 每层的 FFN 复制多份作为 n 个 expert,并增加一个 router,用来计算每个 token 对应到哪个 FFN(一般采用每个 token 固定指派 n 个 exper…

电子病历高质量语料库构建方法与架构项目(临床情景理解模块篇)

引言 随着人工智能技术在医疗健康领域的广泛应用,电子病历(Electronic Medical Records,EMR)作为临床医疗数据的重要载体,已成为医学研究和临床决策支持的关键资源。电子病历高质量语料库的构建为医疗人工智能模型的训练和应用提供了基础支撑,其中临床情境理解模块是连接…

大连理工大学选修课——机器学习笔记(1):概述

机器学习概述 机器学习的本质 机器学习是为了设计解决问题的算法。 为输入与输出建立某种映射: 类似于函数关系: Y f ( X ) Yf(X) Yf(X) 不同的映射方法体现了不同的思想。 相关概念 深度学习是机器学习的一个分支 深度学习是深层次化的神经网…

远程 Debugger 多用户环境下的用户隔离实践

远程 Debugger 多用户环境下的用户隔离实践 在现代分布式开发和云原生环境下,远程 Debugger 的应用愈发普遍。然而,随着多人协作和多租户场景的出现,**远程 Debugger 的“用户隔离”**变得至关重要。只有实现了良好的用户隔离,才…

毕业论文 | 基于C#开发的NMEA 0183协议上位机

以下是基于C#开发的NMEA 0183协议上位机完整实现方案,包含串口通信、数据解析与可视化功能: 基于C#开发的NMEA 0183协议上位机 一、项目结构二、核心代码实现1. 数据模型定义2. 串口通信管理3. NMEA协议解析核心4. 主界面实现(Windows Forms)三、界面设计关键元素(需在窗体…

Qt -DFS可视化

博客主页:【夜泉_ly】 本文专栏:【暂无】 欢迎点赞👍收藏⭐关注❤️ 目录 前言关于如何sleep实现思路Pixmapspixmaps.hpixmaps.cpp MapSquaremapsquare.hmapsquare.cpp dfsthreaddfsthread.hdfsthread.cpprun dfs其他 WidgetUnit其他 Qt -DFS…

RHCSA Linux 系统 文件系统权限

1. 文件的一般权限 (1)文件权限标识解读 drwxr - xr - x. 12 root root 144 Feb 17 16:51 usr ➤d:文件类型(d 表示目录) ➤rwx:文件所有者权限(读 r,写 w,执行 x&am…

华为云IoT平台与MicroPython实战:从MQTT协议到物联网设备开发

目录 前言 1. 华为云 1.1. 创建实例 1.2. 创建产品 1.3. 编辑服务模型 1.4. 注册设备 1.4.1. 复制设备连接参数 1.5. 连接参考代码 2. micropython版-物联网 2.1. 环境搭建 2.2. 实现步骤 2.3. 示例代码 结语 前言 物联网(IoT)技术的快速发…

2025-04-30 AIGC-如何做短片视频

摘要: 2025-04-30 AIGC-如何做短片视频 如何做短片视频: 一、画图修图 1.保存视频(无水保存) 2.文案提取(提取文案) 3. DeepSeek(提示词) 4.小梦Ai(图片视频) 5.修图Ai 6.扩图Ai 7.养生…

硬件工程师面试常见问题(10)

第四十六问:锁存器,触发器,寄存器三者的区别 触发器:能够存储一位二值信号的基本单元电路统称为 "触发器"。(单位) 锁存器:一位触发器只能传送或存储一位数据,而在实际工…

外部访问 Kubernetes 集群中 MQ 服务的方案

外部访问 Kubernetes 集群中 MQ 服务的方案 当您在 Kubernetes 集群中部署了消息队列服务(如 RabbitMQ、Kafka、ActiveMQ 等)后,以下是外部客户端访问这些服务的几种可靠方法: 一、基础访问方案 1. NodePort 方式暴露服务 # M…

论文笔记(八十二)Transformers without Normalization

Transformers without Normalization 文章概括Abstract1 引言2 背景:归一化层3 归一化层做什么?4 动态 Tanh (Dynamic Tanh (DyT))5 实验6 分析6.1 DyT \text{DyT} DyT 的效率6.2 tanh \text{tanh} tanh 和 α α α 的消融实验…

软考中级-软件设计师 操作系统(手写笔记)

第一章:基础知识 第二章:进程管理 状态转换图 进程同步机制 信号量机制 信号量题 死锁 第三章:存储管理 基础知识 分页存储管理 分段存储管理 段页式存储管理 页面置换算法 第四章:文件管理 基础知识 索引分配 空闲存储空间的管…

ubuntu 部署moodle

通过地址https://download.moodle.org/releases/latest/选择下载,下载两种压缩包都特别慢(有可能无法下载)。 可以使用下面git下载项目 注意图中php、mysql等版本要求,本次采用Ubuntu22.04下 nginxphp8.2mysql8.4部署 mkdir /var…

python实战项目67:空气质量在线检测平台js逆向

python实战项目67:空气质量在线检测平台js逆向 一、需求介绍二、完整代码一、需求介绍 项目需求是获取某个城市(以北京市为例)历年(2013年12月至2025年4月)的空气质量数据,字段包括日期、AQI、质量等级、PM2.5、PM10、NO2、CO、SO2等。改网站的网址是“https://www.aqis…

【Linux】记录一个有用PS1

PS1 是用来定义shell提示符的环境变量 下面是一个带有颜色和丰富信息的 Linux PS1 配置示例,包含用户名、主机名、路径、时间、Git 分支和退出状态提示: # 添加到 ~/.bashrc 文件末尾 PS1\[\e[1;32m\]\u\[\e[m\] # 绿色粗体用户名 PS…

Python PyTorch库【机器学习框架】全面深入讲解与实践

一、PyTorch 核心概念 1. 定义与发展背景 PyTorch 是由 Facebook AI Research (FAIR) 开发的开源机器学习框架,2016 年首次发布。其核心特性包括: 动态计算图(Define-by-Run)GPU 加速张量计算自动微分系统丰富的神经网络模块 …

呼叫中心座席管理系统:智能升级,高效服务

在数字化转型加速的今天,客户服务体验已成为企业竞争力的核心要素。传统 呼叫中心系统 依赖硬件设备、人工操作的模式已无法满足高效、智能、灵活的现代企业需求。畅信达呼叫中心 座席管理系统 V5.0应运而生,以WEBRTC软电话接入、智能座席辅助、知识库管…