• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

关于java:Java中的深浅拷贝问题你清楚吗

java 搞代码 3年前 (2022-02-19) 41次浏览 已收录 0个评论

一、前言

拷贝这个词想必大家都很相熟,在工作中常常须要拷贝一份文件作为正本。拷贝的益处也很显著,相较于新建来说,能够节俭很大的工作量。在Java中,同样存在拷贝这个概念,拷贝的意义也是能够节俭创建对象的开销。

Object类中有一个办法clone(),具体方法如下:

<code class="java">protected native Object clone() throws CloneNotSupportedException;
  1. 该办法由 protected 润饰,java中所有类默认是继承Object类的,重载后的clone()办法为了保障其余类都能够失常调用,修饰符须要改成public
  2. 该办法是一个native办法,被native润饰的办法实际上是由非Java代码实现的,效率要高于一般的java办法。
  3. 该办法的返回值是Object对象,因而咱们须要强转成咱们须要的类型。
  4. 该办法抛出了一个CloneNotSupportedException异样,意思就是不反对拷贝,须要咱们实现Cloneable接口来标记,这个类反对拷贝。

为了演示不便,咱们新建两个实体类DeptUser,其中User依赖了Dept,实体类代码如下:

Dept

<code class="java">@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dept {

    private int deptNo;
    private String name;
}

User

<code class="java">@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private int age;
    private String name;
    private Dept dept;
}

二、浅拷贝

对于根本类型的的属性,浅拷贝会将属性值复制给新的对象,而对于援用类型的属性,浅拷贝会将援用复制给新的对象。而像StringInteger这些援用类型,都不是不可变的,拷贝的时候会创立一份新的内存空间来寄存值,并且将新的援用指向新的内存空间。不可变类型是非凡的援用类型,咱们权且认为这些final类型的利用也是复制值。

浅拷贝性能实现

<code class="java">@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Cloneable{

    private int age;
    private String name;
    private Dept dept;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

如何验证咱们的论断呢?首先比照被拷贝出的对象和原对象是否相等,不等则阐明是新拷贝出的一个对象。其次批改拷贝出对象的根本类型属性,如果原对象的此属性产生了批改,则阐明根本类型的属性是同一个,最初批改拷贝出对象的援用类型对象即Dept属性,如果原对象的此属性产生了扭转,则阐明援用类型的属性是同一个。分明测试原理后,咱们写一段测试代码来验证咱们的论断。

<code class="java">public static void main(String[] args) throws Exception{

    Dept dept = new Dept(12, "市场部");
    User user = new User(18, "Java旅途", dept);

    User user1 = (User)user.clone();
    System.out.println(user == user1);
    System.out.println();

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

    dept.setName("研发部");
    System.out.println(user);
    System.out.println(user1);
}

下面代码的运行后果如下

<code class="xml">false

User{age=18, name='Java', dept=Dept{deptNo=12, name='市场部'}}
User{age=20, name='Java', dept=Dept{deptNo=12, name='市场部'}}

User{age=18, name='Java', dept=Dept{deptNo=12, name='研发部'}}
User{age=20, name='Java', dept=Dept{deptNo=12, name='研发部'}}

三、深拷贝

相较于浅拷贝而言,深拷贝除了会将根本类型的属性复制外,还会将援用类型的属性也会复制。

深拷贝性能实现

在拷贝user的时候,同时将user中的dept属性进行拷贝。

dept类:

<code class="java">@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dept implements Cloneable {

    private int deptNo;
    private String name;

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

user来源gaodaimacom搞#^代%!码网类:

<code class="java">@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Cloneable{

    private int age;
    private String name;
    private Dept dept;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        User user = (User) super.clone();
        user.dept =(Dept) dept.clone();
        return user;
    }
}

应用浅拷贝的测试代码持续测试,运行后果如下:

<code class="java">false

User{age=18, name='Java旅途', dept=Dept{deptNo=12, name='市场部'}}
User{age=20, name='Java旅途', dept=Dept{deptNo=12, name='市场部'}}

User{age=18, name='Java旅途', dept=Dept{deptNo=12, name='研发部'}}
User{age=20, name='Java旅途', dept=Dept{deptNo=12, name='市场部'}}

除此之外,还能够利用反序列化实现深拷贝,先将对象序列化成字节流,而后再将字节流序列化成对象,这样就会产生一个新的对象。

参考:再见:深拷贝、浅拷贝问题!——CodeSheep

点关注、不迷路

如果感觉文章不错,欢送关注、点赞、珍藏,你们的反对是我创作的能源,感激大家。

如果文章写的有问题,请不要吝惜文笔,欢送留言指出,我会及时核查批改。

如果你还想看到更多别的货色,能够微信搜寻「Java旅途」进行关注。「Java旅途」目前曾经整顿各种中间件的应用教程及各类Java相干的面试题。


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:关于java:Java中的深浅拷贝问题你清楚吗

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址