最近在开发期间碰上一个关于引用的问题,加注释跟代码研究了好久才发现是对象引用的问题。下文举出了一些常见的传递引用的例子;
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
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实例其实是没有进行拷贝的;引用关系如下图:
那么问题来了,如何将两个list集合中的对象区分开呢?对userList进行 深拷贝 。
深拷贝和浅拷贝的区别在于,在拷贝对象时,是否对引用指向的对象进行拷贝,前者是后者否。
这里涉及到 深拷贝 和 浅拷贝 的知识不在此多展开,有兴趣的同学可以在自己查阅资料了解。
这里推荐一种方式,利用fastJSON,进行两次转换后,获得相同值不同引用的新对象:
String jsonString = JSONObject.toJSONString(userList);
List<User> userList2 = JSONObject.parseArray(jsonString, User.class);