Object类 以及 深浅拷贝

9 阅读3分钟

一、Object类

Java中的Object类,有什么作用。
对于Object类中的方法,按照功能进行划分,简洁告诉我它们的核心作用

1) 类型信息和文本表示(调试/日志)
getClass():返回运行时真实类型(反射入口,知道“这个对象到底是什么类”);
toString():把对象转成可读字符串(默认是 类名@哈希,通常会重写成更有意义的信息)。

2) 相等性与哈希
equals(Object obj):判断“逻辑上是否相等”(默认实现是 ==,也就是同一对象)。
hashCode():返回哈希值(配合 equals 用于 HashMap/HashSet 等散列结构)。
3) 多线程同步:等待/通知(必须在 synchronized 里用)
   
wait() / wait(long) / wait(long,int):
让当前线程在该对象的“监视器锁”上等待,直到被唤醒或超时。
notify():随机唤醒一个正在等待该对象锁的线程。
notifyAll():唤醒所有正在等待该对象锁的线程。
这组方法体现了:每个对象天生都能当作“锁/条件队列”使用(对象自带 monitor)

4)好像没有提到clone(),这个方法不重要or 不常用吗?
确实一般不用;clone() 核心作用:
protected Object clone():复制当前对象,
默认是“浅拷贝”(把字段值按位复制;引用字段只复制引用,不会把引用指向的对象也复制一份)。

二、 浅拷贝
1.“浅拷贝 = 逐字段复制(field-by-field copy)
基本类型,是复制值;
引用类型:复制“引用值”(地址/指针意义上的值),Integer,String也不例外

2.数组/集合是最常见坑
像 int[]、Object[]、ArrayList、自定义对象字段——浅拷贝后,
两边会指向同一个数组/集合/子对象,改一边等于改另一边。

3.浅拷贝不一定“错误”,问题在于“可变共享”
只要共享的是不可变对象,或你明确想共享(比如缓存/只读数据),浅拷贝完全没问题;真正危险的是共享了可变对象还被两边修改

我想看clone()源码,发现它是native,看不到;

4. 外壳是新的,内部引用字段是共用的
   User u2 = u1.clone(); 
   u1 == u2//结果为false
u2指向新建的对象,u1和u2不是同一个对象


import java.util.*;

public class ShallowCopyDemo1 {
    public static void main(String[] args) throws Exception {
        User u1 = new User("A");
        u1.tags.add("java");

        User u2 = u1.clone(); // 浅拷贝

        u2.tags.add("spring"); // 修改 u2 的 tags

        System.out.println("u1.tags = " + u1.tags);
        System.out.println("u2.tags = " + u2.tags);
        System.out.println("same list? " + (u1.tags == u2.tags));
    }

    static class User implements Cloneable {
        String name;
        List<String> tags = new ArrayList<>();

        User(String name) { this.name = name; }

        @Override
        public User clone() throws CloneNotSupportedException {
            return (User) super.clone(); // 只复制引用 -> tags 共享
        }
    }
}


三、深拷贝
深拷贝:新对象 + 内部引用也指向“新拷贝”的对象(尽量不共享可变状态)

深拷贝和浅拷贝在重写时的区别:
我认为:
前者只是简单调用,不在方法体中补充内容,eg:
@Override
        public User clone() throws CloneNotSupportedException {
            return (User) super.clone(); // 只复制引用 -> tags 共享
        }
后者需要
@Override再把可变引用字段复制一份
        public User clone() throws CloneNotSupportedException {
            User copy = (User) super.clone();      // 先浅拷贝外壳
            copy.tags = new ArrayList<>(this.tags); // 再把可变引用字段复制一份
            return copy;
        }
简单来说:
浅拷贝:只 super.clone()
深拷贝:super.clone() + 把所有“可变引用字段”递归复制到不共享为止
补充:
像 String/Integer 这种不可变对象,就算共享引用也安全,所以深拷贝通常只需要处理可变引用字段(数组、集合、Map、自定义可变子对象等)