`

深度克隆与浅度克隆

阅读更多

在java中,无法使 用类直接赋值,即使用Login loginB=loginA;这样的赋值方式,虽然编译起来是没有错的,但往往与实际用法出现叉错.本意是new 一个新类出来,将LoginA的值赋给LoginB,但是,这时候,你会发现,如果你修改了LoginB的值,loginA的值也会随之而改变,这是因为什么呢?

    其实这个原因很简单,因为java不同C语言类的有指针,java是通过直接指向内存的引用而调用对象的

如图:

 java对象类赋值
 
由图可以看出,对像LoginB仍然指向LoginA的堆空间
 
为了解决这种情况,我使用如下的例子:
先定义User类
public class User {
 private int id;
 private String userName;
 private String password;
 
 public int getId() {
  return id;
 }
 public void setId(int id) {
  this.id = id;
 }
 public String getUserName() {
  return userName;
 }
 public void setUserName(String userName) {
  this.userName = userName;
 }
 public String getPassword() {
  return password;
 }
 public void setPassword(String password) {
  this.password = password;
 }
 
}
再定义Login类
public class Login implements Cloneable {
 
 private int id;
 private String loginIp;
 private User loginUser;
 
 public int getId() {
  return id;
 }
 public void setId(int id) {
  this.id = id;
 }
 public String getLoginIp() {
  return loginIp;
 }
 public void setLoginIp(String loginIp) {
  this.loginIp = loginIp;
 }
 public User getLoginUser() {
  return loginUser;
 }
 public void setLoginUser(User loginUser) {
  this.loginUser = loginUser;
 }
 
 public Object clone() {
  Login login=null;
  try {
   login = (Login) super.clone();
  } catch (CloneNotSupportedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return login;
 }
}
测试一:
public class Test {
 public static void main(String[] args) {
  Login loginA=new Login();
  loginA.setId(1000);
  User user = new User();
  user.setId(2000);
  loginA.setLoginUser(user);
  
  Login loginB=loginA;
  loginB.setId(1050);
  loginB.getLoginUser().setId(2050);
  
  System.out.println("loginA id:"+loginA.getId());
  System.out.println("user id:"+user.getId());
 }
}
输出结果:loginA id:1050
         user id:2050
 
测试二:将Test类中的Login loginB=loginA;
              改成:Login loginB=(Login) loginA.clone();
输出结果:loginA id:1000
         user id:2050
由这两个测试,可以看出,使用clone()赋值,与直接赋值的区别,在这里,可以看出Login中的User类的值,无论是使用clone()赋值还是 使用直接赋值,它里面的值都会随着LoginB的改变而改变,但改变LoginB其它内容的时候,LoginA中却不会产生变化,这种情况叫做浅度克隆
     浅度克隆只会将基础数据类型克隆出来,而深层的对像则不会被克隆出来;
     内存图如下:java对象类赋值
注:使用浅度克隆的类除了要重写Object类中的Clone()方法,还必须要实现 Cloneable接口,才可以合法地对该类实例进行按字段复制。
 
为了解决类中类不能被克隆的情况:所以产生了深度克隆
将创建Login类更改成如下:
 
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Login implements Serializable {
 
 private int id;
 private String loginIp;
 private User loginUser;
 
 public int getId() {
  return id;
 }
 public void setId(int id) {
  this.id = id;
 }
 public String getLoginIp() {
  return loginIp;
 }
 public void setLoginIp(String loginIp) {
  this.loginIp = loginIp;
 }
 public User getLoginUser() {
  return loginUser;
 }
 public void setLoginUser(User loginUser) {
  this.loginUser = loginUser;
 }
 
 public Login clone(Login login) {
  Login newLogin=null;
   ByteArrayInputStream bin = null;  
         ByteArrayOutputStream bout = null;  
         try {  
             //把对象对到内存中去  
             bout = new ByteArrayOutputStream();  
             ObjectOutputStream oos = new ObjectOutputStream(bout);  
             oos.writeObject(login);  
             oos.close();  
             //把对象从内存中读出来            
             ByteArrayInputStream bais = new ByteArrayInputStream(bout.toByteArray());  
             ObjectInputStream ois = new ObjectInputStream(bais);  
             newLogin = (Login) ois.readObject();  
             ois.close();  
         } catch (IOException e) {  
             // TODO Auto-generated catch block  
             e.printStackTrace();  
         } catch (ClassNotFoundException e) {  
             // TODO Auto-generated catch block  
             e.printStackTrace();  
         }  
  return newLogin;
 }
 
}
 
 
同时User类也要实现Serializable 接口,目的是标识可序列化
 
测试三:将Test类中的:Login loginB=(Login) loginA.clone();
              改为: Login loginB=new Login().clone(loginA);
 
测试结果:loginA id:1000
         user id:2000
 
由此可以看出,loginB类中的任何值改变了,原赋值中的类的值是不会跟着改变的
内存变化:
java对象类赋值

分享到:
评论

相关推荐

    解析JAVA深度克隆与浅度克隆的区别详解

    本篇文章是对JAVA深度克隆与浅度克隆的区别进行了详细的分析介绍,需要的朋友参考下

    c#深度复制浅度复制

    c#深度复制浅度复制

    C#中深度复制和浅度复制详解

    本文章主要是讲解C# 语言编程中,深度复制和浅度复制,下面我将通过一个实例进行讲解。在实例开发之前,我们得先知道深度复制是什么和浅度复制是什么,它们之间的区别又是什么,下面将为大家一一揭晓。 1.深度复制是...

    ASP.NET深度复制和浅度复制分析

    之前一直没有搞清楚深度复制和浅度复制的区别到底在哪里,今天彻底把这个东西弄懂了,写出来与到家共勉。 如果大家不懂值类型和引用类型的区别,请先看//www.jb51.net/article/57471.htm,本来想自己写的,但刚好...

    javascript克隆对象深度介绍

    克隆或者拷贝分为2种: 浅度克隆:基本类型为值传递,对象仍为引用传递。 深度克隆:所有元素或属性均完全克隆,并于原引用类型完全独立,即,在后面修改对象的属性的时候,原对象不会被修改。 代码如下: function ...

    prototypeAndCreate.zip

    原型实例代码示例 浅度克隆、深度克隆 创建模式代码示例 组装车辆

    网络语言浅度研究报告.doc

    网络语言浅度研究报告.doc

    基于java实现浅度爬虫应用

    基于java实现浅度爬虫应用,是我学习java来练练手的,java爬虫基础入门的学生可以考虑参考一下

    浅度探索C++对象模型bin3.ppt

    浅度探索C++对象模型bin3.ppt

    JRE Hack 浅度研究

    NULL 博文链接:https://lzy.iteye.com/blog/407956

    MyEclipse浅度优化方法

    大家是否觉得MyEclipse启动很慢,那么来看一下吧,如果谁有其他的优化方法,欢迎交流!

    Java中的深拷贝(深复制)和浅拷贝(浅复制)介绍

    主要介绍了Java中的深拷贝(深复制)和浅拷贝(浅复制)介绍,需要的朋友可以参考下

    浅度解析C++运算符重载

    Scott Meyers的著作都一直堪称经典,如《More Effective C++》、《Effective STL》,但由于我憋脚的英语,因此一直与佛无缘。现在好了,有Lostmouse、lians、save 等前辈把这些著作翻译为中文版,让我们这些晚生...

    C#浅拷贝和深拷贝实例解析

    主要介绍了C#浅拷贝和深拷贝,是比较重要的概念,需要的朋友可以参考下

    实例详解vue.js浅度监听和深度监听及watch用法

    主要介绍了vue.js浅度监听和深度监听及watch用法,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友参考下吧

    .NET原型模式讲解

    创建型模式中一个比较特殊的模式-原型模式,有个最大的特点是克隆一个现有的对象,这个克隆的结果有2种,一种是浅度复制,另一种是深度复制。 创建型模式一般是用来创建一个新的对象,然后我们使用这个对象完成一些...

    ajax从基础学起

    内容有:1.ajax入门的三个好例子,很值得学习和借鉴的地方,循序渐进的学习方法 2.ajax的方法从零开始讲起,如何实现,简单明了 3.java的重点介绍,不是纯粹的说说java的语法,既有浅度也有深度,我认为学...

Global site tag (gtag.js) - Google Analytics