美文网首页JAVA小菜鸟排坑系列
【排坑】java 值传递和引用传递

【排坑】java 值传递和引用传递

作者: 汗菜 | 来源:发表于2017-12-21 16:23 被阅读36次

      最近在开发期间碰上一个关于引用的问题,加注释跟代码研究了好久才发现是对象引用的问题。下文举出了一些常见的传递引用的例子;

    java 基本数据类型传递的是值,类、接口、数组传递的是引用

    以下是一些传递引用的例子:

    String str ="abc";
    String str2 = str;  //abc
    str = str2;    //true
    

    str2 = str 是把str指向的内存地址传递给str2,str2存储的是指向 字符串常量池 的内存地址;Tips:字符串常量池中的字符串是不能改变的,内存的大小是不能改变的,有不同的字符串时,会新开辟一块内存保存字符串;

    User user = new User();
    user.setName("张学友");  //张学友
    user.setAge(56);  //56
    
    User user2 = user;  //{"name":"张学友","age":56}
    user2.setAge(18);  //18
    
    user.getAge(); //18
    
    image.png

    user2 = user 是把user指向的内存地址赋值给user2,user2和user同时指向相同的一块内存区域,操作user或user2修改其中的值,另一个的值引用的值也会改变,因为实质是同一块内存存储的值

    User user = new User();
    user.setName("张学友");  
    user.setAge(56);  
                
    User user2 = new User();
    user2.setName("刘德华");  
    user2.setAge(56);  
                
    ArrayList<User> userList = new ArrayList<User>();
    userList.add(user);
    userList.add(user2);
    ArrayList<User> userList2 = new ArrayList<User>(userList); //op1: 开辟一个新的内存地址 
    System.out.println(userList == userList2); //false
    
    userList2.add(new User());  // op2: 给userList2添加一个对象,userList不会变
    System.out.println(userList.size());    //2
                
    for (User u : userList2) {
        u.setAge(18);   //op3: 改变userList2中User对象年龄,user,user2,userList中的值都发生改变
    }
    System.out.println(user.getAge());  //18
    System.out.println(userList.get(0).getAge());  //18
    

    在做op1操作时,相当于对userList进行了拷贝,开辟了一个新的内存进行保存,即userList2,所以跟useList是不同的对象,所以我们在进行op2时,userList并不会增加一个User对象。
    但是在做op3时,我们发现,user对象,user2对象,userList对象中的值都发生了改变,这说明,userList2中User对象其实是存的对user、user2实例的引用。在进行op1的时候,也只是将userList中的对象引用拷贝到了userList2中,对user实例其实是没有进行拷贝的;引用关系如下图:

    image.png

    那么问题来了,如何将两个list集合中的对象区分开呢?对userList进行 深拷贝

    深拷贝和浅拷贝的区别在于,在拷贝对象时,是否对引用指向的对象进行拷贝,前者是后者否。
    这里涉及到 深拷贝浅拷贝 的知识不在此多展开,有兴趣的同学可以在自己查阅资料了解。

    这里推荐一种方式,利用fastJSON,进行两次转换后,获得相同值不同引用的新对象:

    String jsonString = JSONObject.toJSONString(userList);
    List<User> userList2 = JSONObject.parseArray(jsonString, User.class);
    

    相关文章

      网友评论

        本文标题:【排坑】java 值传递和引用传递

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