美文网首页
什么是Java拷贝

什么是Java拷贝

作者: EricDD | 来源:发表于2022-11-29 22:31 被阅读0次

什么是Java拷贝

创建一个和已知对象一摸一样的对象。

创建对象5中方法

  1. new 关键字。
  2. Class 类的 newInstance() 方法。
  3. Constructor 类的 newInstance() 方法。
  4. Object 类 clone() 方法。
  5. 反序列化。
// 克隆必须实现 Cloneable 接口
// 序列化必须实现 Serializable 接口
public class User implements Cloneable, Serializable {
    private String username;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                '}';
    }

    @Override
    public User clone() {
        try {
            return (User) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // new 关键字
        User user = new User();
        user.setUsername("new 关键字");
        System.out.println(user);
        System.out.println(user.hashCode());

        // Class 类的 newInstance() 方法
        Class<?> aClass = Class.forName("cn.eric.register.client.test.User");
        User user1 = (User) aClass.newInstance();
        user1.setUsername("Class 类的 newInstance() 方法");
        System.out.println(user1);
        System.out.println(user1.hashCode());

        // Constructor 类的 newInstance() 方法
        User user2 = User.class.getDeclaredConstructor().newInstance();
        user2.setUsername("Constructor 类的 newInstance() 方法");
        System.out.println(user2);
        System.out.println(user2.hashCode());

        // Object 类 clone() 方法
        User user3 = user.clone();
        System.out.println(user3);
        System.out.println(user3.hashCode());

        // 输出流,序列化写入文件
        String s = "C:\\Users\\Administrator\\Desktop\\a.txt";
        FileOutputStream fileOutputStream = new FileOutputStream(s);
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        objectOutputStream.writeObject(user);
        objectOutputStream.flush();
        
        // 输入流,读取文件,反序列化为对象
        FileInputStream fileInputStream = new FileInputStream(s);
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
        User user4 = (User)objectInputStream.readObject();

        System.out.println(user4);
        System.out.println(user4.hashCode());
    }

基本类型和引用类型

基本类型也称为值类型

char,boolean,byte,short,int,long,float,double

引用类型包括: 类,接口,数组,枚举等

值类型于引用类型.png

浅拷贝

// lombok
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
public class User implements Cloneable, Serializable {
    private String username;
    private Integer age;
    private Cat cat;

    @Override
    public User clone() {
        try {
            return (User) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
public class Cat {
    private String catName;
}
public static void shallowCopy()   {
    User user = new User();
    Cat cat = new Cat();
    cat.setCatName("小白");
    user.setUsername("张三");
    user.setAge(11);
    user.setCat(cat);

    User user1 = user.clone();

    user1.setUsername("李四");
    user1.setAge(12);
    user1.getCat().setCatName("小黑");

    System.out.println(user);
    System.out.println(user1);
    // 输出结果
    // User(username=张三, age=11, cat=Cat(catName=小黑))
    // User(username=李四, age=12, cat=Cat(catName=小黑))
}

所以以上代码 cat 修改后 原 对象也跟着修改了。

浅拷贝.png

String, Integer 也是引用类型为啥没有复制引用而是复制了值呢?

其实不是的 String 和 Integer 其实也是复制了引用. 只是表象让我们看起来像是 复制的 值.

public static void shallowCopy()   {
    User user = new User();
    Cat cat = new Cat();
    cat.setCatName("小白");
    user.setUsername("张三");
    user.setAge(11);
    user.setCat(cat);

    User user1 = user.clone();

    //        user1.setUsername("李四");
    //        user1.setAge(12);
    //        user1.getCat().setCatName("小黑");

    System.out.println(user);
    System.out.println(user1);


    System.out.println("user.hash" + user.hashCode());
    System.out.println("user1.hash" + user1.hashCode());
    System.out.println("user.username.hash" + user.getUsername().hashCode());
    System.out.println("user1.username.hash" + user1.getUsername().hashCode());
    System.out.println(user.getUsername() == user1.getUsername());

    //        输出内容
    //        User(username=张三, age=11, cat=Cat(catName=小白))
    //        User(username=张三, age=11, cat=Cat(catName=小白))
    //        user.hash46723090
    //        user1.hash46723090
    //        user.username.hash774889
    //        user1.username.hash774889
    //        true
}

我们发现如果我们注释掉修改 username 的代码 发现 username 的 hash 值是一摸一样的。而且 == 对比也是相等的.

说明 字符串 其实确实是复制的引用。 看起来像是值引用的原因就是 String 类是 final 修饰的

String 是不可变的。修改就是重新创建一个字符串并将栈内的指向改为新创建的堆。

Integer 同理。

String不可变.png

深拷贝

深拷贝就是所有字段都拷贝一份.即使是引用类型对象也一样.

实现方法就是所有的引用类型对象也实现一下 Cloneable接口. 并重写 clone方法.

但是此时有个问题.例如 上方代码 User 类里不仅仅有 Cat 还有 Dog 还有 Duck 等等.... Cat 里面还有 Snacks 等等 一层一层一个一个又一个的对象. 代码量就多了.

使用反序列化实现 深拷贝是个不错的办法. 注意: 所有的类都要实现Serializable接口序列化才行.

相关文章

  • Java基础 - 深拷贝和浅拷贝

    Java 的深拷贝和浅拷贝 什么是深拷贝、浅拷贝 (深克隆、浅克隆)? 在 Java 中,数据类型分为 基本数据类...

  • 什么是Java拷贝

    什么是Java拷贝 创建一个和已知对象一摸一样的对象。 创建对象5中方法 new 关键字。 Class 类的 ne...

  • 什么是浅拷贝和深拷贝?

    创建Java对象的方式包括new、反射、反序列化、拷贝,那么什么是拷贝呢?浅拷贝和深拷贝又有什么区别呢? 什么是拷...

  • Java 最近遇到的面试题

    JAVA 基础 java 对象拷贝深浅拷贝 对象何时进入老年代 Minor GC 和 Full GC 有什么不同 ...

  • java 对象的拷贝

    拷贝:即复制 对象拷贝:即对象复制 java 对象拷贝分类:浅拷贝、深拷贝 java 对象的浅拷贝和深拷贝针对包含...

  • Java参数传递是值传递

    篇首语:Java基本类型传递的是值的拷贝,Java引用类型传递的是对象地址的拷贝。 在java中,java是通过值...

  • Android Kotlin 设计模式之原型模式

    前言 继续填坑,这次是原型模式 什么是原型模式 首先在java里面是存在深拷贝和浅拷贝的 深拷贝: 完全复制生成一...

  • Java基础系列-浅拷贝和深拷贝

    原创文章,转载请标注出处:《Java基础系列-浅拷贝和深拷贝》 一、概述 Java中的拷贝功能是由Object类的...

  • Java复制

    概述 Java复制分为三类:直接赋值、浅拷贝和深拷贝。 Java复制是基于Object的clone()方法。 由此...

  • Java------List的深拷贝与浅拷贝

    Java的浅拷贝(Shallow Copy)、深拷贝(Deep Copy)。 浅拷贝(Shallow Copy) ...

网友评论

      本文标题:什么是Java拷贝

      本文链接:https://www.haomeiwen.com/subject/zeljfdtx.html