首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Java Collection(5)——比较(数据/对象)&深浅拷贝(对象)

Java Collection(5)——比较(数据/对象)&深浅拷贝(对象)

作者头像
用户11873138
发布2026-01-13 21:08:27
发布2026-01-13 21:08:27
880
举报

1.比较

1.1 基本数据类型的比较

Java中基本数据类型可以通过 == , > , < 这三个运算符来比较 还可以使用其对应的包装类调用equals方法来比较

在这里插入图片描述
在这里插入图片描述

1.2引用类型的比较

我这里创建了一个自定义类student

在这里插入图片描述
在这里插入图片描述

Object类自带的equals方法实际上和==差不多,用<和>更是会直接报错 既然如此,该如何实现对象之间的比较呢? 以下会展示三种方法

1.3 对象的比较

1.3.1 重写Object中的equals方法

重写之后就可以调用自己的equals方法

在这里插入图片描述
在这里插入图片描述
1.3.2 实现Comparable接口

实现Comparable接口,然后在该类中重写compareTo方法

在这里插入图片描述
在这里插入图片描述

因为在StudengA内部重写compareTo方法,所以以后比较StudentA类型的大小,只能比较它的id大小(除非改变StudentA内部的compareTo方法),对类的侵入性较强

1.3.3 提供比较器(Comparator)

创建一个类来实现Comparator接口,并且重写接口里的compare方法

在这里插入图片描述
在这里插入图片描述

相较于实现Comparable接口,比较器对类的侵入性没那么强,可以按照提供的比较器来实现不同的比较逻辑

1.4 为什么要实现对象的比较?

因为在优先级队列/TreeMap(举的例子)中,如果要往里面添加元素,则添加的元素必须是可比较的,否则会报错,下面以TreeMap为例

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.5 三个比较方式对比

1.Object.equals:因为所有类都是继承自 Object 的,所以直接覆写即可,不过只能比较相等与否 2.Comparable.compareTo:需要手动实现接口,侵入性比较强,但一旦实现,每次用该类都有顺序,属于内部顺序 3.Comparator.compare:需要实现一个比较器对象,对待比较类的侵入性弱

2.深浅拷贝(2025年5月11日新增)

Java SE(5)——数组中介绍了Arrays工具类,调用其中的copyOf()方法可以完成对数组的拷贝

那么,如果想要对一个对象进行拷贝又应该怎么样实现呢?

代码语言:javascript
复制
public class CopyPerson {
    public String name;
    public int age;
    public int score;
    //
    public CopyPerson(String name, int age, int score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}
public class Copy {
    public static void main(String[] args){
        CopyPerson person1 = new CopyPerson("张三",18,98);
        CopyPerson person2 = person1;
        System.out.println(person2);
    }
}

运行结果: Person{name=‘张三’, age=18, score=98} 在上述代码中,仅看运行结果貌似是完成了一个对象的拷贝,但实际上只是将原对象的地址赋值给新的引用而已,在堆中仍然只存在一份对象

在这里插入图片描述
在这里插入图片描述

下面就讲解如何将对象完整地在堆中拷贝一份

2.1 浅拷贝

在Java中有专门拷贝对象的方法:Object类中的clone方法(如下)。

代码语言:javascript
复制
protected native Object clone() throws CloneNotSupportedException;

该clone()方法是由native修饰,表示该方法的具体实现是使用C/C++写的,我们无法查看方法的内部代码。因为Object类默认是所有类的父类,所以如果要使用该方法只需要在子类中重写就行了 修改后代码如下:

代码语言:javascript
复制
public class ShallowPerson implements Cloneable {
    public String name;
    public int age;
    public int score;
    //
    public ShallowPerson(String name, int age, int score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class ShallowClone {
    //浅拷贝
    public static void main(String[] args) throws CloneNotSupportedException {
        ShallowPerson person1 = new ShallowPerson("张三",18,98);
        ShallowPerson person2 = (ShallowPerson) person1.clone();
        System.out.println(person1);
        System.out.println(person2);
        //修改person2的age
        person2.age = 20;
        System.out.println(person1);
        System.out.println(person2);
    }
}

运行结果: Person{name=‘张三’, age=18, score=98} Person{name=‘张三’, age=18, score=98} Person{name=‘张三’, age=18, score=98} Person{name=‘张三’, age=20, score=98} 根据运行结果可知,修改person2中的age值并没有影响person1中的age值,所以可以判定person1和person2指向的是两个对象

在这里插入图片描述
在这里插入图片描述

注意:被拷贝的类必须实现Cloneable接口,这个接口中没有任何方法,实现该接口的类也不会重写任何方法,但是会被声明为可拷贝的(Cloneable)。换言之,实现Cloneable接口后会被赋予可拷贝的权限,如果不实现该接口直接重写并调用clone()方法会抛出CloneNotSupportedException异常(不支持拷贝)

问题一:上述代码中,子类重写的clone()方法貌似并没有改变内部逻辑,依然是调用父类的clone()方法,那么重写的意义是什么?

在这里插入图片描述
在这里插入图片描述

对比子类和Object中的clone()方法,唯一的区别就是访问限定修饰符,那么把protected修改为public的作用是什么呢? 被protected修饰的成员,在同一个包中可以被任意的类访问,在不同的包中只能在子类中访问。在不重写clone()方法的情况下,ShallowPerson只能在自己的内部调用clone()方法,而无法在ShallowClone中通过ShallowPerson的引用来访问clone()方法(protected成员的访问权限是基于类层级结构(继承)和包结构的,而不是对象的引用)

问题二:当被拷贝的类中存在其他引用变量时(如自定义类),上述的拷贝还能顺利完成吗? 拷贝不彻底,位置关系图如下:

在这里插入图片描述
在这里插入图片描述

要想把Money对象也进行拷贝,仅需要进行深拷贝操作

2.2 深拷贝

代码语言:javascript
复制
public class DeepPerson implements Cloneable {
    public String name;
    public int age;
    public int score;
    public Money money;
    //
    public DeepPerson(String name, int age, int score,int money) {
        this.name = name;
        this.age = age;
        this.score = score;
        this.money = new Money(money);
    }
    @Override
    public String toString() {
        return "DeepPerson{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                ", money=" + money +
                '}';
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
//Money类中也实现Cloneable接口并重写clone()方法
public class Money implements Cloneable {
    public int money;
    //
    public Money(int money) {
        this.money = money;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    @Override
    public String toString() {
        return "Money{" +
                "money=" + money +
                '}';
    }
}
public class DeepClone {
    public static void main(String[] args) throws CloneNotSupportedException {
        DeepPerson deepPerson1 = new DeepPerson("李四",20,100,25000);
        DeepPerson deepPerson2 = (DeepPerson) deepPerson1.clone();
        System.out.println(deepPerson1);
        System.out.println(deepPerson2);
        deepPerson2.money = new Money(26000);
        System.out.println(deepPerson1);
        System.out.println(deepPerson2);
    }
}

运行结果:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-10-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.比较
    • 1.1 基本数据类型的比较
    • 1.2引用类型的比较
    • 1.3 对象的比较
      • 1.3.1 重写Object中的equals方法
      • 1.3.2 实现Comparable接口
      • 1.3.3 提供比较器(Comparator)
    • 1.4 为什么要实现对象的比较?
    • 1.5 三个比较方式对比
  • 2.深浅拷贝(2025年5月11日新增)
    • 2.1 浅拷贝
    • 2.2 深拷贝
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档