前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >我要拷贝你—Java对象

我要拷贝你—Java对象

作者头像
码上积木
发布2020-12-25 10:04:51
4500
发布2020-12-25 10:04:51
举报
文章被收录于专栏:码上积木码上积木
上期答案

5-1-10-6-9-3-2-9-8-7

9-3-2-9-8-7

  • 先初始化父类(静态方法,代码块):5,1
  • 然后初始化子类 (静态方法,代码块):10,6
  • super()(父类非静态变量,父类的非静态代码块,父类的构造方法):9,3,2
  • 实例化子类(非静态变量,非静态代码块,构造方法):9,8,7

前言

java中,如果我要拷贝(复制)一个对象该怎么做呢?今天就和大家一起看看Java中的拷贝。

基础知识—数据类型

首先要了解一下Java中的数据类型,主要有两类:

  • 基本类型

也就是八大数据类型:byte,short,int,long,char,float,double,boolean。基本数据类型在声明时,系统就给它分配数据空间,无论是否赋值。

  • 引用类型。 包括 类,接口和数组 。引用类型在声明时只是给变量分配了引用空间,并不分配数据空间。

相等就是拷贝吗?

好了,了解了基础知识后,开始今天的拷贝问题。拷贝是什么呢?是用等号就可以完成的操作吗?看个例子:

代码语言:javascript
复制
public class User {
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

定义usera的年龄为20,userb=usera,那么userb是拷贝了usera吗?

代码语言:javascript
复制
public void main {
         User usera = new User();
         usera.setAge(20);
         User userb = usera;
         //修改usera的年龄
         usera.setAge(22);
         //输出userb的年龄,会发现也是22
         Log.e("", userb.getAge() + "");
}

我们可以发现,其实=并不是拷贝了对象,而是直接使用了usera对象的引用地址,也就是说usera和userb其实是一个人,没有拷贝。

那么,怎么拷贝呢?

浅拷贝

两步,完成对象的拷贝(浅拷贝)

  • 实现Cloneable接口
  • 重写clone方法
代码语言:javascript
复制
public class User2 implements Cloneable {
        private int age;
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        
        @NonNull
        @Override
        public Object clone() {
            User2 user2 = null;
            try {
                user2 = (User2) super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return user2;
        }
    }

然后再调用clone方法就可以完成对象的拷贝(浅拷贝)了

代码语言:javascript
复制
public void main() {
       User2 usera = new User2();
       usera.setAge(20);
       User2 userb = (User2) usera.clone();
       //修改usera的年龄
       usera.setAge(22);
       //输出userb的年龄,还是11
       Log.e("", userb.getAge() + "");
}

ok,至此完成了对象的拷贝(浅拷贝)了。大家估计也发现了,我在每个拷贝后面都加了一个 「(浅拷贝)」,拷贝为啥还分深浅呢?下面看一个案例

给user类增加一个对象变量

代码语言:javascript
复制
public class Favorite {
        private String sport;
        private String color;
        public String getSport() {
            return sport;
        }
        public void setSport(String sport) {
            this.sport = sport;
        }
        public String getColor() {
            return color;
        }
        public void setColor(String color) {
            this.color = color;
        }
    }

    public class User3 implements Cloneable {
        private int age;
        private Favorite favorite;

        public Favorite getFavorite() {
            return favorite;
        }

        public void setFavorite(Favorite favorite) {
            this.favorite = favorite;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        @NonNull
        @Override
        public Object clone() {
            User3 user2 = null;
            try {
                user2 = (User3) super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return user2;
        }
    }

然后再去进行一个拷贝(浅拷贝)

代码语言:javascript
复制
public void main(String[] args) {
        User3 usera = new User3();
        Favorite favorite = new Favorite();
        favorite.setColor("蓝色");
        usera.setAge(20);
        usera.setFavorite(favorite);
        User3 userb = (User3) usera.clone();
        //修改usera的年龄和爱好颜色
        usera.setAge(22);
        usera.getFavorite().setColor("红色");
        //输出userb的年龄,还是11
        Log.e("", userb.getAge() + "");
        //输出userb的爱好,变成了红色!!
        Log.e("", userb.getFavorite().getColor() + "");
    }

这里我们发现,拷贝之后,年龄确实没变化,但是favorite 却跟着变了?所以,大概了解了:

  • 浅拷贝意思就是只拷贝对象中的基本数据类型,而引用数据类型还是引用传递,没有创建一个新的对象, 其实就是值传递+引用传递
  • 深拷贝呢就是对其中的引用数据类型进行拷贝的时候,创建了一个新的对象,并完全复制了其内的成员变量,简单点说,深拷贝就是可以copy对象的所有值,使得两个对象完全不影响。

所以继续看看怎么实现深拷贝

深拷贝

深拷贝就是要把对象里面所有对象也进行拷贝,完整整个对象的真正拷贝,直接上代码

代码语言:javascript
复制
public class Favorite2 implements Cloneable {
        private String sport;
        private String color;

        public String getSport() {
            return sport;
        }

        public void setSport(String sport) {
            this.sport = sport;
        }

        public String getColor() {
            return color;
        }

        public void setColor(String color) {
            this.color = color;
        }

        @Override
        public Object clone() {
            Favorite2 addr = null;
            try {
                addr = (Favorite2) super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return addr;
        }
    }

    public class User4 implements Cloneable {
        private int age;
        private Favorite2 favorite;

        public Favorite2 getFavorite() {
            return favorite;
        }

        public void setFavorite(Favorite2 favorite) {
            this.favorite = favorite;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        @NonNull
        @Override
        public Object clone() {
            User4 user4 = null;
            try {
                user4 = (User4) super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            user4.favorite = (Favorite2) favorite.clone();
            return user4;
        }
    }

    public class copyObject3 {
        public void main(String[] args) {
            User4 usera = new User4();
            Favorite2 favorite = new Favorite2();
            favorite.setColor("蓝色");
            usera.setAge(20);
            usera.setFavorite(favorite);
            User4 userb = (User4) usera.clone();
            //修改usera的年龄和爱好颜色
            usera.setAge(22);
            usera.getFavorite().setColor("红色");
            //输出userb的年龄,还是11
            Log.e("", userb.getAge() + "");
            //输出userb的爱好,还是蓝色
            Log.e("", userb.getFavorite().getColor() + "");
        }
    }

这样不仅是实体类里面的普通变量,还有对象变量全部都被拷贝一份出来了,也就完成了深拷贝。

总结

  • 浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝。
  • 深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。

思考

今天也留一个思考题吧:

Kotlin中数据类有个方法可以完成拷贝,你知道是什么吗?这个方法是深拷贝还是浅拷贝呢?

参考

https://www.cnblogs.com/lmj612/p/10874052.html

感谢大家的阅读,有一起学习的小伙伴可以关注下公众号—码上积木❤️ 每日三问知识点/面试题,积少成多。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-12-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码上积木 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 基础知识—数据类型
  • 相等就是拷贝吗?
  • 浅拷贝
  • 深拷贝
  • 总结
  • 思考
  • 参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档