【Java】抽象类接口

news2024/11/17 14:35:21

目录

1.抽象类

2.接口

2.1实现多个接口

2.2接口之间的关系

2.3接口使用实例

2.3.1Comparable接口

2.3.2Comparator接口

2.3.2Clone接口

2.4抽象类与接口的区别


1.抽象类

定义:抽象方法:这个方法没有具体的实现;

           抽象类:不能完全代表一个具体的对象。

注意

1> 使用 abstract 修饰;

2> 抽象类不能进行实例化,但普通类可以;

3> 抽象类中不一定包含抽象方法,但包含抽象方法的类一定是抽象类;

4> 抽象类中可以定义普通的成员变量和成员方法;

5> 抽象类存在的最大意义就是为了被继承,且多了一层编译器的校验;

6> 普通类继承抽象类后要重写抽象类中的抽象方法;

7> 抽象类A继承抽象类B后不需要重写,但当普通类C再继承抽象类A后,要重写所有没被重写的抽象方法;

8> 要满足重写的要求(如static和private不能被重写);

9> final关键字不可能和abstract同时作用在一个类或方法上;

10> 抽象类当中可以存在构造方法,在子类实例化时,会帮助父类的成员进行初始化。

abstract class Shape { //抽象类
    public int a;//普通成员变量
    public void print() { //普通成员方法
        System.out.println("Shape");
    }
    public abstract void draw(); //抽象方法
}
class Cycle extends Shape { //普通类
    @Override //普通类继承抽象类后要重写抽象类中的抽象方法
    public void draw() {
        System.out.println("○");
    }
}
abstract class Flower extends Shape {
    //抽象类继承抽象类,可以不重写父类的抽象方法
    abstract public void printf();//抽象方法
}
class Square extends Flower {
    @Override //见注意事项6
    public void draw() {
        System.out.println("□");
    }
    @Override
    public void printf() {
        System.out.println("❀");
    }
}

2.接口

定义:对公共行为的规范标准,是一种引用数据类型。相当于抽象类的进一步抽象。

注意

1> 使用 interface 定义;

2> 接口中不能有实现的方法,但是静态方法和被default修饰的方法可以实现;

3> 接口中的成员方法默认是public abstract修饰的;

4> 接口中的成员变量默认是public static final 修饰的;

5> 不能通过关键字new来实例化;

6> 类和接口之间使用implement进行关联;

7> 类实现接口后要重写接口中的抽象方法

8> 接口中存在default方法时可重写可不重写,具体看业务需求;

9> 不论是接口还是抽象类,都有向上转型

10> 子类实现接口方法时,这个方法一定要public修饰;

11> 接口中没有构造方法和代码块

12> 当一个类不想实现接口当中的方法时,这个类可以被定义为抽象类;

13> 接口的修饰符可以为abstract、public,不能为protected、private、final

interface IShape { //接口
    //成员方法默认为public abstract修饰,顾下列方法均为抽象方法
    public abstract void draw1();//抽象方法不可实现,public abstract可省略
    public void draw2();//抽象方法不可实现,public可省略
    public static void draw3() { //静态方法可以实现
        System.out.println("draw3");
    }
    default public void draw4() { //被default修饰的方法可以实现
        System.out.println("draw4");
    }
}
class Cycle implements IShape { //Cycle类实现了IShape接口
    @Override //重写接口中的抽象方法
    public void draw1() {
        System.out.println("○");
    }
    @Override //重写接口中的抽象方法
    public void draw2() {
        System.out.println("□");
    }
}
class Rect implements IShape { //同上
    @Override
    public void draw1() {
        System.out.println("□");
    }
    @Override
    public void draw2() {
        System.out.println("○");
    }
}
public class Test {
    public static void drawMap(IShape shape) { //多态
        shape.draw1();
    }

    public static void main(String[] args) {
        //IShape iShape = new IShape();//接口无法实例化自己
        IShape iShape1 = new Cycle();
        IShape iShape2 = new Rect();//向上转型

        drawMap(new Cycle());
        drawMap(new Rect());
    }
}

2.1实现多个接口

意义:一个类实现多个接口,可以解决Java中多继承的问题

注意:先继承类,再实现接口。

interface IFlying { //接口1
    void fly();
}
interface ISwimming { //接口2
    void swim();
}
interface IRunning { //接口3
    void run();
}
abstract class Animal { //抽象父类
    public String name;
    public int age;
    public Animal(String name, int age) { //带两个参数的构造方法
        this.name = name;
        this.age = age;
    }
    public abstract void eat(); //抽象方法
}
class Dog extends Animal implements IRunning,ISwimming{ //子类1
    public Dog(String name, int age) { //子类的构造方法
        super(name, age);
    }
    @Override //重写父类和接口的抽象方法
    public void swim() {
        System.out.println(this.name+"正在狗刨");
    }
    @Override
    public void run() {
        System.out.println(this.name+"正在跑");
    }
    @Override
    public void eat() {
        System.out.println(this.name+"正在吃狗粮");
    }
}
class Bird extends Animal implements IFlying { //子类2
    public Bird(String name, int age) { //子类的构造方法
        super(name, age);
    }
    @Override //重写父类和接口的抽象方法
    public void fly() {
        System.out.println(this.name+"正在飞");
    }
    @Override
    public void eat() {
        System.out.println(this.name+"正在吃虫子");
    }
}
public class Test {
    public static void testEat(Animal animal) { //多态
        animal.eat();
    }
    public static void testFly(IFlying iFlying) { //多态
        iFlying.fly();
    }
    public static void testRun(IRunning running) { //多态
        running.run();
    }
    public static void testSwim(ISwimming iSwimming) { //多态
        iSwimming.swim();
    }
    public static void main(String[] args) {
        testEat(new Bird("小鸟",3));
        testEat(new Dog("小狗",3));
        testFly(new Bird("小小鸟",2));
        testRun(new Dog("小小狗",2));
        testSwim(new Dog("小小小狗",1));
    }
}

2.2接口之间的关系

接口与接口之间关联用 extends,意为拓展,非继承。相当于把接口合并在一起。

interface A {
    void testA();
}
interface B {
    void testB();
}
interface C extends A,B { //此时C接口不仅有自己的功能,还有A接口和B接口的功能
    void testC();
}
class D implements C { //ABC中的抽象方法都要重写
    @Override
    public void testA() {
    }
    @Override
    public void testB() {
    }
    @Override
    public void testC() {
    }
}

2.3接口使用实例

2.3.1Comparable接口

//只根据年龄或成绩比较:

import java.util.Arrays;
class Student implements Comparable<Student>{ //当对自定义类型进行比较时,一定要实现可比较的接口
    public String name;
    public int age;
    public double score;
    public Student(String name, int age, double score) { //带三个参数的构造方法
        this.name = name;
        this.age = age;
        this.score = score;
    }
    @Override //重写Comparable接口中的抽象方法
    public int compareTo(Student o) { //按年龄排序
        /*if (this.age - o.age > 0) {
            return 1;
        } else if (this.age - o.age == 0) {
            return 0;
        }else {
            return -1;
        }*/
        return this.age - o.age;
    }
}
public class Test {
    //模拟实现冒泡排序
    public static void bubbleSort(Comparable[] comparables) { //传入Comparable类型(实现了可比较接口)的数组
        for (int i = 0; i < comparables.length-1; i++) {
            for (int j = 0; j < comparables.length-1-i; j++) {
                //if (comparables[j]>comparables[j+1]) //无法直接比较
                if(comparables[j].compareTo(comparables[j+1]) > 0) { //使用重写的compareTo方法比较
                    Comparable tmp = comparables[j];
                    comparables[j] = comparables[j+1];
                    comparables[j+1] = tmp;
                }
            }
        }
    }
    public static void main(String[] args) {
        Student[] array = new Student[2];
        array[0] = new Student("zhangsan",20,88.8);
        array[1] = new Student("lisi",18,90);
        bubbleSort(array); //冒泡排序
        System.out.println("排序后:"+Arrays.toString(array));
    }
    public static void main2(String[] args) {
        Student student1 = new Student("xiaoming",14,98.5);
        Student student2 = new Student("xiaohong",16,59.9);
        int ret = student1.compareTo(student2);
        System.out.println(ret); //-1
    }
    public static void main1(String[] args) {
        Student[] array = new Student[3];
        array[0] = new Student("zhangsan",20,88.8);
        array[1] = new Student("lisi",18,90);
        array[2] = new Student("wangwu",21,68.9);
        System.out.println("排序前:"+ Arrays.toString(array));
        Arrays.sort(array); //Java自带的方法
        System.out.println("排序后:"+ Arrays.toString(array));
    }
}

2.3.2Comparator接口

//年龄成绩均可比较: 更加灵活

import java.util.Comparator;
class Student{
    public String name;
    public int age;
    public double score;
    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
}
class AgeComparator implements Comparator<Student> { //比较年龄
    @Override
    public int compare(Student o1, Student o2) {
        return o1.age - o2.age;
    }
}
class ScoreComparator implements Comparator<Student> { //比较成绩
    @Override
    public int compare(Student o1, Student o2) {
        return (int)(o1.score - o2.score);//score为double类型,需要强转为int类型
    }
}
public class Test {
    public static void main(String[] args) {
        Student student1 = new Student("xiaoming",14,98.5);
        Student student2 = new Student("xiaohong",16,59.9);

        AgeComparator ageComparator = new AgeComparator();
        int ret = ageComparator.compare(student1,student2);
        System.out.println(ret);//-2

        ScoreComparator scoreComparator = new ScoreComparator();
        int ret2 = scoreComparator.compare(student1,student2);
        System.out.println(ret2);//38
    }
}

2.3.2Clone接口

class Student implements Cloneable { //实现Cloneable接口
    public int age;
    public Student(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                '}';
    }
    @Override
    protected Object clone() throws CloneNotSupportedException { //异常
        return super.clone();//子类重写的Object只是调用了父类的clone方法
    }
}
public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student1 = new Student(18);
        Student student2 = (Student) student1.clone();//向下转型,clone类型为Object,需强转为Student
        System.out.println(student1);//Student{age=18}
        System.out.println(student2);//Student{age=18} 克隆成功
    }
}

Ctrl+点击进入Cloneable接口后发现,该接口内什么东西都没有,why??

:这个接口被叫做标记接口,实现该接口证明当前的类是可以被克隆的。

//浅拷贝 

class Money {
    public double money;
}
class Student implements Cloneable { 实现Cloneable接口
    public int age;
    public Money m = new Money();
    public Student(int age) {
        this.age = age;
    }
    @Override //重写接口中的抽象方法
    protected Object clone() throws CloneNotSupportedException { 
        return super.clone();
    }
}
public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student1 = new Student(18);
        student1.m.money = 9.15;
        Student student2 = (Student) student1.clone();//克隆student1

        System.out.println(student1.m.money);//9.15
        System.out.println(student2.m.money);//9.15

        student1.m.money = 10;//更改student1
        System.out.println(student1.m.money);//10 按理说只有student1变
        System.out.println(student2.m.money);//10 但是实际上两个都变了
                                             //这就是浅拷贝,没有克隆当前对象内更深层的变量
    }
}

//深拷贝

class Money implements Cloneable { //实现Cloneable接口
    public double money;
    @Override //重写接口中的抽象方法
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
class Student implements Cloneable { //实现Cloneable接口
    public int age;
    public Money m = new Money();
    public Student(int age) {
        this.age = age;
    }
    @Override //重写接口中的抽象方法
    protected Object clone() throws CloneNotSupportedException {
       Student tmp = (Student) super.clone();//先克隆当前对象
       tmp.m = (Money) this.m.clone();//再克隆当前对象里更深层的变量
       return tmp;
    }
}
public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student1 = new Student(18);
        student1.m.money = 9.15;
        Student student2 = (Student) student1.clone();//克隆student1

        System.out.println(student1.m.money);//9.15
        System.out.println(student2.m.money);//9.15

        student1.m.money = 10;//更改student1
        System.out.println(student1.m.money);//10    深拷贝,只修改了student1
        System.out.println(student2.m.money);//9.15  不影响student2内的值
    }
}

2.4抽象类与接口的区别

区别

抽象类(abstract)接口(interface)
结构组成普通成员变量+抽象方法抽象方法+全局变量
权限各种权限public
子类使用使用extends继承抽象类使用implement实现接口
关系一个抽象类可以实现若干接口借口不能继承抽象类,但可使用extends拓展多个父接口
子类限制一个子类只能继承一个抽象类一个子类可以实现多个接口

Over!五一结束啦~~

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

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

相关文章

边学边记——数据结构☞和搜索有关的数据结构(搜索树,Set,Map,哈希表)

目录 模型 一、搜索 1. 场景 2. 搜索树 2.1 概念 2.2 查找 2.3 插入 2.4 删除 2.5 实现 2.6 性能分析 2.7 和Java的关系 二、Set 1. 常见方法 2. 注意 三、Map 1. 关于Map.Entry的说明,> 2. Map的常用方法说明 3. 注意 四、哈希表 1. 概念 2. 冲突 2…

[论文分享] VOS: Learning What You Don‘t Know by Virtual Outlier Synthesis

这篇文章是ICLR‘ 2022的一篇文章。 No.contentPAPER{ICLR’ 2022} VOS: Learning What You Don’t Know by Virtual Outlier SynthesisURL论文地址CODE代码地址 Motivation 现有OOD Detection方法大多依赖于真实的离群点数据集进行模型正则化&#xff0c;实际应用中过于昂…

常用位运算

一、求解二进制表示的第k位数字 #include<iostream> using namespace std;int main() {int n 10; // 例如&#xff0c;十进制10用二进制表示为1010 for(int k3;k>0;k--)cout << (n >> k & 1);// 第一步&#xff1a;右移k位// 第二步&#xff1a; &am…

JVM基础总结

文章目录 一、程序计数器二、Java虚拟机栈栈内存溢出【StackOverflowError】线程运行诊断 三、本地方法栈【Native Method Stacks】四、堆【Head】线程共享堆内存溢出【OutOfMemoryError&#xff1a;Java heap space】堆内存诊断 五、方法区【Method Area】线程共享运行时常量池…

Springboot +Flowable,为流程设置租户

一.简介 什么叫flowable的租户呢&#xff1f;这边举个例子&#xff1a; 假设现在有 A、B、C、D 四个子系统&#xff0c;四个子系统都要部署同一个名为 leave 的流程&#xff0c;如何区分四个不同子系统的的流程呢&#xff1f;通过租户就可以解决这个问题。Flowable 中的租户其…

dell r750服务器安装centos系统全记录

1、启动盘制作 1.1 下载系统 打开 https://www.centos.org/download/ 任意选择一个镜像网站&#xff0c;博主选择的是163镜像 下载内存为4g镜像文件 这里也可以参考 https://blog.csdn.net/weixin_46703995/article/details/121191113 1.2 下载启动盘制作软件 linux系统一…

Denoising Diffusion Probabilistic Model,DDPM阅读笔记——(二)

Denoising Diffusion Probabilistic Model&#xff0c;DDPM阅读笔记 一、去噪扩散概率模型&#xff08;Denoising Diffusion Probabilistic Model&#xff0c;DDPM&#xff09; 一、去噪扩散概率模型&#xff08;Denoising Diffusion Probabilistic Model&#xff0c;DDPM&…

C++数据结构:手撕红黑树

目录 一. 红黑树的概念及结构 二. 红黑树节点的定义 三. 红黑树节点的插入 3.1 初步查找插入节点的位置并插入节点 3.2 红黑树结构的调整 3.3 红黑树节点插入完整版代码 四. 红黑树的结构检查 4.1 检查是否为搜索树 4.2 检查节点颜色是否满足要求 附录&#xff1a;红黑…

TypeScript进阶

目录 TypeScript 与 Vue 文档说明 vscode 插件说明 准备页面基本结构 defineProps与Typescript defineEmits与Typescript ref与Typescript reactive与Typescript computed与Typescript 事件对象与Typescript 模板Ref与Typescript 可选链操作符和非空断言 TypeScript…

21.网络爬虫—js逆向详讲与实战

网络爬虫—js逆向 js逆向JavaScript逆向的详细讲解实战演示有道翻译设置密钥和初始向量对密钥和初始向量进行哈希处理创建AES对象并解密消息移除padding并返回结果 前言&#xff1a; &#x1f3d8;️&#x1f3d8;️个人简介&#xff1a;以山河作礼。 &#x1f396;️&#x1f…

python基于卷积神经网络实现自定义数据集训练与测试

样本取自岩心照片&#xff0c;识别岩心是最基础的地质工作&#xff0c;如果用机器来划分岩心类型则会大大削减工作量。 下面叙述中0指代Anhydrite_rock&#xff08;膏岩&#xff09;&#xff0c;1指代Limestone&#xff08;灰岩&#xff09;&#xff0c;2指代Gray Anhydrite_r…

深度学习-第T6周——好莱坞明星识别

深度学习-第T6周——好莱坞明星识别 深度学习-第T6周——好莱坞明星识别一、前言二、我的环境三、前期工作1、导入数据集2、查看图片数目3、查看数据 四、数据预处理1、 加载数据1、设置图片格式2、划分训练集3、划分验证集4、查看标签 2、数据可视化3、检查数据4、配置数据集 …

Flutter学习之旅 - 页面布局Stack层叠组件

文章目录 StackPositioned定位布局浮动导航(StackPositioned)FlutterMediaQuery获取屏幕宽度和高度StackAlign Stack Stack意思是堆的意思&#xff0c;我们可以用Stack结合Align或者Stack结合Positioned来实现页面的定位布局 属性说明alignment配置所有元素显示位置children子组…

23.Lambda表达式

Lambda表达式 一、Lambda表达式背景 Lambda 表达式(lambda expression)是一个匿名函数&#xff0c;Lambda表达式基于数学中的λ演算得名&#xff0c;直接对应于其中的lambda抽象(lambda abstraction)&#xff0c;是一个匿名函数&#xff0c;即没有函数名的函数。Lambda表达式…

2023-05-05 背包问题

背包问题 1 01背包和完全背包问题 01背包问题 有N件物品和一个容量为V的背包&#xff0c;第i件物品的体积是v[i]、价值是w[i]&#xff0c;每种物品只可以使用一次&#xff0c;求将哪些物品放入背包可以使得价值总和最大。这里的w是weight即权重的意思 这是最基础的背包问题&a…

【飞书ChatGPT机器人】飞书接入ChatGPT,打造智能问答助手

文章目录 前言环境列表视频教程1.飞书设置2.克隆feishu-chatgpt项目3.配置config.yaml文件4.运行feishu-chatgpt项目5.安装cpolar内网穿透6.固定公网地址7.机器人权限配置8.创建版本9.创建测试企业10. 机器人测试 转载自远控源码文章&#xff1a;飞书接入ChatGPT - 将ChatGPT集…

Ubuntu 如何查看 CPU 架构、系统信息、内核版本、版本代号?

Ubuntu 查看 CPU 架构、系统信息、内核版本、版本代号等相关信息有很多方式&#xff0c;本文介绍几种常用的命令。 x86 架构与 ARM 架构的 CPU 架构不同&#xff0c;如果回显为 aarch64 表示为 ARM 架构&#xff0c;如果回显为 x86_64 表示为 x86 架构&#xff0c;参考《CPU 架…

Prometheus快速入门

Prometheus快速入门 环境准备 三台主机&#xff0c;配置好主机名 各自配置好主机名 # hostnamectl set-hostname --static server.cluster.com ... 三台都互相绑定IP与主机名 # vim /etc/hosts 192.168.126.143 server.cluster.com 192.168.126.142 agent.clu…

归并排序(看了就会)

目录 概念1. 基本思想2. 实现逻辑3. 复杂度分析4、代码 概念 归并排序&#xff0c;是创建在归并操作上的一种有效的排序算法。算法是采用分治法&#xff08;Divide and Conquer&#xff09;的一个非常典型的应用&#xff0c;且各层分治递归可以同时进行。归并排序思路简单&…

智头条|欧盟达成《人工智能法》协议,全球前沿科技齐聚AWE 2023

行业动态 华为云联手多方推进数字化&#xff0c;软通动力深度参与 华为云宣布启动“‘百城万企’应用现代化中国行”&#xff0c;旨在推动应用现代化进程、助力数字中国高质量落地。软通动力是该行动的参与者之一&#xff0c;共同探索符合区域特点、产业趋势、政企现状的数字化…