Java学习【接口的使用实例,浅克隆与深克隆】

news2024/9/20 0:52:40

Java学习【接口的使用实例,浅拷贝与深拷贝】

  • Comparable接口
    • String类型比较
    • 多个对象的比较
  • Comparator接口
  • Cloneable接口
    • 浅拷贝
    • 深拷贝

Comparable接口

当我们想要比较两个基本数据类型的大小时直接用 > , < , = 就可以了,那么如果是自定义的类要根据什么规则进行比较呢?这就用到了Comparable接口,接口中定义的就是一种规范,通过重写接口中的compareTo方法,定义比较规则,就实现了自定义类型的比较

//调用接口
class Man implements Comparable<Man>{
    public String name;
    public int age;
    public Man(String name,int age){
        this.name = name;
        this.age = age;
    }
	
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
//重写接口方法
    @Override
    public int compareTo(Man m) {
        return this.age - m.age;
    }
}
public class Text01 {
    public static void main(String[] args) {
        Man man1 = new Man("li",18);
        Man man2 = new Man("wang",20);
        System.out.println(man1.compareTo(man2));//输出-2
    }
}

在这里插入图片描述

谁调用compareTo方法,this就代表谁

在这里插入图片描述

String类型比较

上面比较的age是整型,可以相减,那如果是String 类型呢
在这里插入图片描述
可以看出,Java中的String类也实现了Comparable接口,同时也重写了compareTo方法
在这里插入图片描述
那么我们只需要调用就可以了

@Override
    public int compareTo(Man m) {
        return this.name.compareTo(m.name);
    }

多个对象的比较

import java.util.Arrays;

class Man implements Comparable<Man>{
    public String name;
    public int age;
    public Man(String name,int age){
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public int compareTo(Man m) {
        return this.name.compareTo(m.name);
    }

}
public class Text01 {
    public static void main(String[] args) {
        Man man1 = new Man("li",18);
        Man man2 = new Man("wang",20);
        Man man3 = new Man("zhang",22);
        Man[] men = {man1,man2,man3};
        //使用Arrays类的sort方法对数组进行排序
        Arrays.sort(men);
        System.out.println(Arrays.toString(men));
    }
}

运行结果:
在这里插入图片描述
可以看出,是按照重写后的compareTo方法进行排序的

在这里插入图片描述
这一次程序报错了,类型转换的错误
在这里插入图片描述
当点到出错的地方来看
在这里插入图片描述
当把之前的注释取消,源码底层就会把Man强转为Comparable,调用compareTo方法,而此时由于compareTo重写了,就会调用重写后的方法,排序也会根据重写之后的compareTo方法进行排序。

简单模拟一下Array.sort对自定义类型的排序

public static void main(String[] args) {
        Man man1 = new Man("li",18);
        Man man2 = new Man("wang",20);
        Man man3 = new Man("zhang",22);
        Man[] men = {man1,man2,man3};
        //使用Mysort方法对数组进行排序
        Mysort(men);
        System.out.println(Arrays.toString(men));
    }
public static void Mysort(Comparable[] comparables){
        for(int i = 0;i < comparables.length - 1;i++){
            for(int j = 0;j< comparables.length - 1 - i;j++){
                //如果后面的元素比前面的元素小,则交换它们的位置
                if(comparables[j].compareTo(comparables[j+1]) > 0){
                    Comparable temp = comparables[j];
                    comparables[j] = comparables[j+1];
                    comparables[j+1] = temp;
                }
            }
        }
    }

所以当调用Arrays.sort给自定义的类型进行排序的时候,也必须实现Comparable的接口

但是无论是比较age还是name,用以上方法都比较固定,不够灵活,为了解决这个问题,我们来介绍下一个接口

Comparator接口

public class BrandComparator implements Comparator<Car>{

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

调用接口之后重写compare方法

public static void main(String[] args){
        Car car1 = new Car("benz","black",200);
        Car car2 = new Car("audi","white",250);
        Car[] cars = {car1,car2};
        //使用Comparator接口的compare方法
        BrandComparator brandComparator = new BrandComparator();
        //传入比较器
        Arrays.sort(cars,brandComparator);
        //toString方法
        System.out.println(Arrays.toString(cars));
        for(Car car:cars){
            System.out.println("品牌:" + car.getBrand());
            System.out.println("颜色:" + car.getColor());
            System.out.println("速度:" + car.getSpeed());
        }
    }

也可以直接调用方法,单独比较

BrandComparator brandComparator = new BrandComparator();
        int res = brandComparator.compare(car1,car2);
        System.out.println(res);

这样就比较灵活,想要根据哪个属性比较,就定义一个类去实现Comparator接口,再定义比较的规则

Cloneable接口

public class Person {
    public String name;
    public int age;

    public Person() {
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

创建一个Person类之后,实现对象的克隆
在这里插入图片描述
虽然Person类里面没有clone方法,但是Object类里面有,每一个类都默认继承与Object类,但此时还是报错了,这就需要在Person类中重写clone方法
在这里插入图片描述

@Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

加上之后还是错的,原因是,自定义类型想要进行克隆还要实现Cloneable接口
在这里插入图片描述
点进源码发现Cloneable接口没有写任何方法,是一个空接口,空接口也叫做标记接口,表示当前类是可以被克隆的
在这里插入图片描述
之后还要处理一下异常,再对返回值类型进行强转,因为此时返回的是Object类型的,这样就可以正常执行了

public static void main(String[] args) throws CloneNotSupportedException{
        Person person1 = new Person("张三", 20);
        Person person2 = (Person) person1.clone();
    }

在这里插入图片描述
具体过程就是创建person1对象之后,再克隆一份数据,创建person2,把克隆出的数据赋值给person2

浅拷贝

在这里插入图片描述
在原来的基础上再加上一个Money类,此时再对克隆后的值进行修改
在这里插入图片描述
在这里插入图片描述
可以看出,当把person1的money修改之后,两个是都会发生改变的,这种就叫做浅拷贝
在这里插入图片描述
此时就是只克隆了Person的对象,没有克隆Money的对象

深拷贝

如果想要Money也进行克隆,就需要实现Cloneable接口,同时重写clone方法

class Money implements Cloneable{
    public double money = 9.9;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

Person类的clone也要重写
在这里插入图片描述
在这里插入图片描述
Person克隆之后,Money也进行克隆,就是深拷贝
在这里插入图片描述

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

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

相关文章

为什么我们应该放弃定义敏感数据?

个人数据与人以及其他个人数据深深地交织在一起&#xff0c;它就像一幅巨大的挂毯&#xff0c;而这些线是无法轻易拆开的。尝试定义敏感数据就像徒劳地试图从挂毯中找出不同的线头一样&#xff0c;线头与其他线头交织在一起&#xff0c;一旦开始拆线&#xff0c;整个挂毯就会散…

IP地址概述和配置

一.IP地址的概述 在计算机网络中&#xff0c;连接的网络设备和计算机都有唯一的地址&#xff0c;以此作为该计算机在internet中的唯一标识。 二.IP地址的定义 IP地址&#xff08;internet protocol Address&#xff0c;网络协议地址&#xff09;是用于表示网络节点的逻辑地址…

黄石首家Pearson VUE国际认证考试中心落户湖北理工学院

Pearson VUE 作为 Pearson 集团的专门从事计算机化考试服务的公司&#xff0c;到目前为止&#xff0c;已在全世界165 个国家授权了 4400 多个考试中心以及超过 230 家 PVUE 自有考试中心&#xff0c;其中在中国的有三百多个授权考点和 4 个自有考试中心。Pearson VUE 以其技术和…

虚拟列表 vue-virtual-scroller 的使用

npm 详情&#xff1a;vue-virtual-scroller - npm (npmjs.com) 这里我使用的是RecycleScroller。 App.vue <template><RecycleScrollerclass"scroller":items"items":item-size"54"v-slot"{ item }"><list-item :it…

『光谷云智慧大屏』数字智慧型 案例赏析

设计背景 随着数字化转型的不断深入&#xff0c;智慧大屏在云数据处理中心扮演着越来越重要的角色。大屏采用先进技术&#xff0c;构建了一个直观且互动的实时数据监控系统。它不仅提高了数据处理的效率&#xff0c;还为数据中心的智能化管理和运营提供了强有力的支持&#xf…

智慧工地势在必行,可以减少管理的无序状态,效率倍增。

智慧工地的建设对于提高工地管理效率和减少无序状态具有重要意义。智慧工地通过引入先进的信息技术和智能化设备&#xff0c;可以实现以下方面的优势&#xff1a; 1. 实时监测和管理&#xff1a; 智慧工地可以通过传感器、监控摄像头等设备对施工现场的各种参数和情况进行实时…

RGMII接口及时序详解

文章目录 一、RGMII接口介绍二、MAC和PHY1.关系2.MAC和PHY的交互3.MAC为什么要配置PHY4.如何配置&#xff08;1&#xff09;原理&#xff08;2&#xff09;PHY地址的确定&#xff08;3&#xff09;寄存器地址及配置数据 三、88E1111中PHY的时序1.接收端时序&#xff08;1&#…

Windows安全应急--应急排查的一些方法

前言&#xff1a; 非法BC植入网站安全应急&#xff0c; 在安全应急中&#xff0c; 总会需要大大小小的问题&#xff0c; 就像成长一样。 检测工具尽量使用轻量级的。。 本次演示环境 Windows Server 2008 问题排查步骤&#xff1a; 先判断服务器有没有被Rootkit 查看登录…

将联表查询到的数据按1000一批次存入数据库-模板

idea模板&#xff1a; /*** ${Shitilei}信息 服务层实现。** author admin*/ Service RequiredArgsConstructor public class Operate${Shitilei}Service {private final ${Shitilei}Mapper ${shitilei}Mapper;private final RegionUtil util;/*** ${shitilei}表* return 操作结…

【抽代复习笔记】18-置换练习题(2)及两个重要定理

最近一直忙于学校的事情&#xff0c;好久没更新了&#xff0c;实在抱歉。接下来几期大概也会更得慢一些&#xff0c;望见谅。 练习4&#xff1a;写出4次对称群S4中所有置换。 解&#xff1a;由上一篇笔记结尾的定理我们知道&#xff0c;4次对称群的阶&#xff08;也就是所含元…

SAP-有历史业务情况下的物料批次切换前提条件和方案建议

转载自&#xff1a;SAP-有历史业务情况下的物料批次切换前提条件和方案建议 - 知乎 (zhihu.com) 在SAP中&#xff0c;物料是否启用批次管理主要是通过物料上的“批次管理”字段进行控制&#xff0c;但物料批次管理涉及库存很多业务节点的控制&#xff0c;因此一旦有业务的发生&…

超市生鲜如何持续盈利?

生鲜经营是现代超市功能配置中不可缺少的组成部分&#xff0c;通过生鲜区经营及其效果可以反映出超市业态发展的成熟化程度。做好了可以达到集客和盈利的目的&#xff0c;做得不好&#xff0c;也很容易成为超市中的亏损&#xff0c;更难指望顾客经常光顾。 超市生鲜区生存和发展…

QT creator centralwidget前面有个禁止符号

centralwidget前面有个禁止符号&#xff1a;表示分拆布局 在主窗口空白处&#xff0c;右键&#xff0c;选择布局即可选择不同的布局方式&#xff0c;表示对窗口内所有控件部件进行布局&#xff0c;不如垂直布局。

Android模块化项目搭建和模块之间跳转传值(2)

一、前言 这是一篇关于Android模块化的项目搭建和配置&#xff0c;没有看过我第一部分的同学如果不清楚整个流程的&#xff0c;可以回头看一下&#xff0c;有利于你更加快速的掌握和使用。 二、引入ARouter 模块化顾名思义就是将项目按模块的方式进行开发&#xff0c;加大了…

C++小病毒

C小病毒&#xff08;注&#xff1a;对电脑无过大伤害&#xff09; 短短行&#xff0c;创造奇迹&#xff01; 把这个文件命名为virus.exe就可以使用了。 #include<bits/stdc.h> #include<windows.h> using namespace std; int main() {HWND hwnd GetForegroundW…

一图看懂 | 蓝卓新材料行业解决方案

小到芯片、手机、智能手表&#xff0c;大到智能装备、新能源汽车、光伏电池板&#xff0c;新材料的运用不可缺少。作为未来产业的“基石”&#xff0c;新材料行业有力支撑了航空航天、电子信息、新能源等战略性新兴产业的发展壮大。 七大行业特点&#xff0c;五大应用场景&…

【WEEK13】 【DAY3】Shiro第三部分【中文版】

2024.5.22 Wednesday 接上文【WEEK13】 【DAY2】Shiro第二部分【中文版】 目录 15.4.登录拦截15.4.1.修改ShiroConfig.java15.4.2.新建login.html页面15.4.3.修改MyController.java15.4.4.再次修改ShiroConfig.java15.4.5.重启 15.5.用户认证15.5.1.修改MyController.java15.5.…

【css】引入背景图时候,路径写入@会报错

看报错信息 我的写法 解决办法 在前面加个~

个体因果效应估计|EDVAE:用于个体治疗效果估计的反事实推理中的解开潜在因素模型

【摘要】根据观察数据估计个体治疗效果&#xff08;ITE&#xff09;是一项至关重要但具有挑战性的任务。解缠结表示已用于将代理变量分为混杂变量、工具变量和调整变量。然而&#xff0c;根据观测数据准确地进行反事实推理来识别 ITE 仍然是一个悬而未决的问题。在本文中&#…

6. Spring面试题汇总

Java全栈面试题汇总目录-CSDN博客 1. 什么是Spring框架? Spring是一种轻量级开发框架&#xff0c;旨在提高开发人员的开发效率以及系统的可维护性。 我们一般说Spring框架指的都是Spring Framework&#xff0c;它是很多模块的集合&#xff0c;使用这些模块可以很方便地协助…