Java语言-接口(下)

目录

1. 接口使用实例

1.1 给对象数组排序

1.2  Clonable接口和深拷贝

Cloneable

浅拷贝

深拷贝

1.3 抽象类和接口的区别

2. Object类

2.1 Object类的介绍

2.2 toString()

2.3 equals()

2.4 hashcode()



1. 接口使用实例

1.1 给对象数组排序

现有一个学生类:

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+"]";
    }
}
再给定一个学生对象数组 , 对这个对象数组中的元素进行排序 ( 按分数降序 ).
public static void main(String[] args) {
        Student[] students={
                new Student("zhangsan",95),
                new Student("lisi",92),
                new Student("wangwu",97),
                new Student("zhaoliu",90)
        };
}

在数组类 Arrays 里,我们有一个现成的方法 sort ,比如以下案例:

        int[] arr={1,3,2,4,6,5,9,8,7};
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));

对于学生类Student组成的数组,不能直接使用这个方法:

原因:两个整数是可以进行比较的,但是两个学生对象的大小关系无法直接确定...

让我们的 Student 类实现 Comparable 接口 , 并实现其中的 compareTo 方法
sort 方法中会自动调用 compareTo 方法
然后比较当前对象和参数对象的大小关系 ( 按分数来算 ).
如果当前对象应排在参数对象之前 , 返回小于 0 的数字 ;
如果当前对象应排在参数对象之后 , 返回大于 0 的数字 ;
如果当前对象和参数对象不分先后 , 返回 0;
再次执行程序 , 结果就符合预期了 .

为了进一步加深对接口的理解 , 我们可以尝试自己实现一个 sort 方法来完成刚才的排序过程
(使用冒泡排序)
public static void sort(Comparable array[]){
        for (int bound = 0; bound < array.length; bound++) {
            for (int cur = array.length-1; cur > bound; cur--) {
                if(array[cur-1].compareTo(array[cur])>0){
                    Comparable tmp=array[cur];
                    array[cur]=array[cur-1];
                    array[cur-1]=tmp;
                }
            }
        }
    }
再次执行代码
        sort(students);
        System.out.println(Arrays.toString(students));

如果我们不想要按照分数的高低来排序,而是按照名字来排序,应该如何写?

重写compareTo方法如下:

    @Override
    public int compareTo(Student o) {
        return this.name.compareTo(o.name);
    }

然而,这种写法有一个明显的缺陷:

不适合灵活的比较,只适合用于固定的比较。

比如,想要从按照分数比较换成按名字比较,就需要重新写一个compareTo方法,使用起来不方便...

解决方法:换一个接口。(使用 Comparator 接口)

另外写两个类,实现Comparator接口,分别实现按名字比较和按分数比较的功能:

class ScoreComparator implements Comparator<Student>{

    @Override
    public int compare(Student o1, Student o2) {
        return o1.getScore()-o2.getScore();
    }
}

class NameComparator implements Comparator<Student>{

    @Override
    public int compare(Student o1, Student o2) {
        return o1.getName().compareTo(o2.getName());
    }
}

然后将以上两个类分别实例化,用哪个类作为参数传入Arrays.sort中,就按哪种方式比较:

        //实例化两个类
        ScoreComparator scoreComparator=new ScoreComparator();
        NameComparator nameComparator=new NameComparator();

        //按照分数比较
        Arrays.sort(students,scoreComparator);
        System.out.println(Arrays.toString(students));
        //按照名字比较
        Arrays.sort(students,nameComparator);
        System.out.println(Arrays.toString(students));

1.2  Clonable接口和深拷贝

Cloneable

Java 中内置了一些很有用的接口 , Clonable 就是其中之一 .
Object 类中存在一个 clone 方法 , 调用这个方法可以创建一个对象的 " 拷贝 ". 但是要想合法调用 clone 方法 , 必须要先实现 Clonable 接口 , 否则就会抛出 CloneNotSupportedException 异常 .

案例:

class Animal implements Cloneable{
    private String name;
    private int age;
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "Animal{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class Demo3 {
    public static void main(String[] args) throws CloneNotSupportedException {
        Animal animal1=new Animal("小财",3);
        Animal animal2=(Animal) animal1.clone();
        System.out.println(animal1);
        System.out.println(animal2);
    }
}

【注意事项】

1.要调用对象的clone()方法,首先要在类里面重写clone()方法。

2.clone方法要处理CloneNotSupportedException异常,否则编译器会报错。

3.clone()方法的返回值是Object类型,需要向下转型才能接收。

4.类要实现Cloneable接口,否则运行编译器会抛出 CloneNotSupportedException异常.

克隆过程图解:


增加一个类Money,并且该类实例化对象作为类Person的成员变量:

class Money{
    public double val=9.9;
}
class Person implements Cloneable{
    private String name;
    private int age;
    public Money money=new Money();
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

浅拷贝

案例:

public class Demo3 {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person p1= new Person("zhangsan",10);
        Person p2= (Person) p1.clone();
        System.out.println("修改前:"+p1.money.val);
        System.out.println("修改前:"+p2.money.val);
        p1.money.val=99;
        System.out.println("修改后:"+p1.money.val);
        System.out.println("修改后:"+p1.money.val);
    }
}

运行结果:

可以看到:改变p1的成员money后,p2的成员money也跟着改变了——这就是潜拷贝。

分析原因:

原因:money是一个引用变量,可以理解为p1的引用变量money里面储存了对象new Money()的地址,而克隆出来的p2的引用变量跟p1的引用变量储存了同一个地址,因此修改p1的money,p2的money也会改变。


深拷贝

更改Person类里的重写方法,将克隆出来的新对象的引用变量成员money指向另一个对象(不是跟p1的对象同一个):

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person tmp=(Person) super.clone();
        //tmp.money=new Money();//写法1
        tmp.money=(Money) this.money.clone();//写法2
        return tmp;
    }

再次运行的结果:

1.3 抽象类和接口的区别

核心区别 : 抽象类中可以包含普通方法和普通字段 , 这样的普通方法和字段可以被子类直接使用 ( 不必重写 ), 而接口中不能包含普通方法, 子类必须重写所有的抽象方法 .
【注意】
抽象类存在的意义是为了让编译器更好的校验, 像 Animal 这样的类我们并不会直接使用, 而是使用它的子类.
万一不小心创建了 Animal 的实例, 编译器会及时提醒我们.
      No        区别       抽象类(abstract)                  接口(interface)
      1结构组成普通类+抽象方法抽象方法+全局变量
      2权限各种权限public
      3子类使用使用extends关键字继承抽象类使用implements关键字实现接口
     4关系一个抽象类可以实现若干个接口接口不能继承抽象类,但是接口可以使用extends关键字继承多个父接口
     5子类限制一个子类只能继承一个抽象类一个子类可以实现多个接口

2. Object类

2.1 Object类的介绍

Object Java 默认提供的一个类。 Java 里面除了 Object 类,所有的类都是存在继承关系的。 默认会继承Object父类 。即所有类的对象都可以使用Object 的引用进行接收。
范例:使用 Object 接收所有类的对象
class Animal {
}
class Person{
}
public class Demo3 {
    public static void function(Object o){
    System.out.println(o);
}
    public static void main(String[] args) {
        function(new Animal());
        function(new Person());
    }
}

Object类中包含了很多方法。

本次学习中,我们主要学习这几个方法:toString()方法,equals()方法,hashcode()方法

2.2 toString()

Animal类默认继承Object类,重写toString方法如下:

class Animal {
    private String name;
    private int age;
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Animal{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Demo3 {
    public static void main(String[] args) {
        System.out.println(new Animal("旺财",3));
    }
}

2.3 equals()

Java 中, == 进行比较时:
a. 如果 == 左右两侧是基本类型变量,比较的是变量中值是否相同
b. 如果 == 左右两侧是引用类型变量,比较的是引用变量地址是否相同
c. 如果要比较对象中内容,必须重写Object中的equals方法,因为equals 方法默认也是按照地址比较的:
// Object 类中的 equals 方法
public boolean equals ( Object obj ) {
return ( this == obj ); // 使用引用中的地址直接来进行比较
}

使用案例:

没有重写equals方法如下:

class Person{
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
public class Demo3 {
    public static void main(String[] args) {
        Person p1=new Person("张三",18);
        Person p2=new Person("张三",18);
        System.out.println(p1.equals(p2));
    }
}

重写了equals方法如下:

class Person{
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null ) return false;
        //不是Person类
        if(!(o instanceof Person)) return false;

        Person person = (Person) o;
        return this.age == person.age && this.name.equals(person.name);
    }

}

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

2.4 hashcode()

    public static void main(String[] args) {
        Person p1=new Person("张三",18);
        Person p2=new Person("张三",18);
        System.out.println(p1.hashCode());
        System.out.println(p2.hashCode());
    }
调用hashCode() 这个方法,他会帮我算一个具体的 对象位置。
我们认为两个名字相同,年龄相同的对象,将存储在同一个位置,如果不重写 hashcode() 方法,
算出来的位置(hash值)就会不一样

如果要使算出来的位置一样,就需要重写 hashcode() 方法:

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

对象p1和p2的name和age都相同,那么将name和age作为条件传入hash方法中,算出来的hash值就是一致的:


如果哪里有疑问的话欢迎来评论区指出和讨论,如果觉得文章有价值的话就请给我点个关注还有免费的收藏和赞吧,谢谢大家!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Let‘s Verify Step by Step(openai-o1论文技术调研)

Let’s Verify Step by Step openai的经典论文&#xff0c;发布于2023年5月31日&#xff0c;为当前openai-o1奠定了技术基础&#xff0c;同时开源了PRM800K数据集&#xff0c;为开源社区贡献了十分宝贵的参考 paper原文链接 : https://arxiv.org/abs/2305.20050 论文概述 当前…

VUE, element-plus, table分页表格列增加下拉筛选多选框,请求后台

简介 为了方便表格查询时可以筛选列的值&#xff0c;需要给列增加筛选框&#xff08;多选框&#xff09;&#xff0c;element-plus提供了列的filter字段&#xff0c;但是基于表格数据的筛选&#xff0c;不会重新请求后台&#xff0c;而且当前表格数据有多少个条目&#xff0c;…

Makefile Npm

还是习惯强类型语法: typescript 不错 vue 非常好的模组 也是很好的学习模板 编译完才6MB 相当可以了 时代发展有点快 导入echarts 模块编译完才1.7MB 好用 <script> import {VaButton, VaInput} from "vuestic-ui";export default {components: {VaInput, VaB…

20241028在荣品PRO-RK3566开发板的预置Android13下用iperf3测试AP6256的WIFI网速

20241028在荣品PRO-RK3566开发板的预置Android13下用iperf3测试AP6256的WIFI网速 2024/10/28 18:17 荣品PRO-RK3566开发板作为服务器端&#xff1a; 笔记本电脑作为客户端。 接公司的网络。 在笔记本电脑的ubuntu20.04下&#xff0c;通过nethogs实测iperf3的发送速度大概是10MB…

Bi-LSTM-CRF实现中文命名实体识别工具(TensorFlow)

项目源码获取方式见文章末尾&#xff01; 回复暗号&#xff1a;13&#xff0c;免费获取600多个深度学习项目资料&#xff0c;快来加入社群一起学习吧。 **《------往期经典推荐------》**项目名称 1.【MobileNetV2实现实时口罩检测tensorflow】 2.【卫星图像道路检测DeepLabV3P…

【ArcGIS Pro实操第4期】绘制三维地图

【ArcGIS Pro实操第4期】绘制三维地图 ArcGIS Pro绘制三维地图-以DEM高程为例参考 如何使用ArcGIS Pro将栅格数据用三维的形式进行表达&#xff1f;在ArcGIS里可以使用ArcScene来实现&#xff0c;ArcGIS Pro实现原理跟ArcScene一致。由于Esri未来将不再对ArcGIS更新&#xff0c…

Python酷库之旅-第三方库Pandas(174)

目录 一、用法精讲 801、pandas.Categorical类 801-1、语法 801-2、参数 801-3、功能 801-4、返回值 801-5、说明 801-6、用法 801-6-1、数据准备 801-6-2、代码示例 801-6-3、结果输出 802、pandas.Categorical.from_codes方法 802-1、语法 802-2、参数 802-3、…

2.5 塑性力学—应变状态

个人专栏—塑性力学 1.1 塑性力学基本概念 塑性力学基本概念 1.2 弹塑性材料的三杆桁架分析 弹塑性材料的三杆桁架分析 1.3 加载路径对桁架的影响 加载路径对桁架的影响 2.1 塑性力学——应力分析基本概念 应力分析基本概念 2.2 塑性力学——主应力、主方向、不变量 主应力、主…

在房价涨声一片中,购房者更要看好钱袋,千万不要冲动入坑!

近几个月以来诸多媒体都传出房价上涨的好消息&#xff0c;二手房东也连连传出反价的消息&#xff0c;似乎房价真的到底了&#xff0c;一些购房者因此可能被市场的波动而冲动买房&#xff0c;笔者认为这个时候反而要更慎重地看待房价。 房价的低点确实很难预测&#xff0c;不过1…

单链表OJ题(2):反转链表、找中间节点

目录 1.反转链表 反转链表总结&#xff1a; 2.链表的中间节点&#xff08;快慢指针法&#xff09; 快慢指针法总结 1.反转链表 在这道题中&#xff0c;我们需要把一个单链表反转它们的指向&#xff0c;这里&#xff0c;我们给出了一个好理解的简单解法&#xff0c;就是用三…

C++ 日志管理 spdlog 使用笔记

文章目录 Part.I IntroductionChap.I 预备知识Chap.II 常用语句 Part.II 使用Chap.I 简单使用Chap.II 自定义日志格式 Part.III 问题&解决方案Chap.I 如果文件存在则删除 Reference Part.I Introduction spdlog 是一个开源的 C 日志管理工具&#xff0c;Git 上面的地址为 …

在html中引用unpkg的vue3,v-model无法绑定方法

如果用下面代码引用vue使用&#xff0c;则注意v-model无法绑定方法。 <script src"https://unpkg.com/vue3/dist/vue.global.js"></script> 例如&#xff1a; <span>方法-全名&#xff1a;</span><input type"text" v-model&…

如何将原本打开Edge呈现出的360浏览器,更换成原本的Edge页面或者百度等其他页面

每次打开Edge浏览器&#xff0c;都会呈现出360浏览器的页面&#xff0c;很烦。以下将说明如果将呈现出的360浏览器&#xff0c;更换成原本的Edge页面或者百度等其他页面。 1.找到你的控制面板&#xff0c;点击卸载程序。 2. 找到360安全卫士&#xff0c;右键单击更改/卸载。 3…

【深度学习|地学应用】人工智能技术的发展历程与现状:探讨深度学习在遥感地学中的应用前景

【深度学习|地学应用】人工智能技术的发展历程与现状&#xff1a;探讨深度学习在遥感地学中的应用前景 【深度学习|地学应用】人工智能技术的发展历程与现状&#xff1a;探讨深度学习在遥感地学中的应用前景 文章目录 【深度学习|地学应用】人工智能技术的发展历程与现状&…

抖音评论采集 可采子评论

下载&#xff1a;【1】https://drive.uc.cn/s/5257861b109b4?public1 【2】https://pan.quark.cn/s/e54155575698

python pip更换(切换)国内镜像源

国内镜像源列表(个人推荐清华大学的源) ​ 清华大学&#xff1a; https://pypi.tuna.tsinghua.edu.cn/simple阿里云&#xff1a; http://mirrors.aliyun.com/pypi/simple豆瓣&#xff1a; http://pypi.douban.com/simple中国科技大学&#xff1a; https://pypi.mirrors.ustc.e…

Linux 重启命令全解析:深入理解与应用指南

Linux 重启命令全解析&#xff1a;深入理解与应用指南 在 Linux 系统中&#xff0c;掌握正确的重启命令是确保系统稳定运行和进行必要维护的关键技能。本文将深入解析 Linux 中常见的重启命令&#xff0c;包括功能、用法、适用场景及注意事项。 一、reboot 命令 功能简介 re…

福鼎自闭症全托干预:为福鼎地区自闭症患者提供个性化教育

在探讨自闭症儿童的教育与干预时&#xff0c;个性化与全面关怀成为了不可忽视的关键词。福鼎地区的自闭症全托干预项目&#xff0c;以其对患儿个体差异的深刻理解与尊重&#xff0c;为自闭症患者提供了量身定制的支持。而在遥远的广州&#xff0c;星贝育园自闭症儿童寄宿制学校…

js基础入门篇

1.输出语句&#xff0c;内部样式&#xff0c;外部样式&#xff0c;数组定义 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.…

Oracle OCP认证考试考点详解082系列01

题记&#xff1a; 本篇博文是Oracle OCP认证考试考点详解082系列的第一篇&#xff0c;本系列主要讲解Oracle OCP认证考试考点&#xff08;题目&#xff09;&#xff0c;适用于19C/21C,跟着学OCP考试必过。 1. 第一题&#xff1a; 1. 题目 2. 解析及答案 关于Oracle数据库中节…