精华内容
下载资源
问答
  • java序列化克隆 开发人员经常依靠3d方库来避免重新发明轮子,尤其是在Java世界中,Apache和Spring这样的项目如此盛行。 在处理这些框架时,我们通常很少或根本无法控制其类的行为。 这有时会导致问题。 例如,...

    java序列化深克隆

    开发人员经常依靠3d方库来避免重新发明轮子,尤其是在Java世界中,Apache和Spring这样的项目如此盛行。 在处理这些框架时,我们通常很少或根本无法控制其类的行为。

    这有时会导致问题。 例如,如果您想深克隆一个不提供合适克隆方法的对象,除了编写大量代码之外,您还有什么选择?

    通过序列化克隆

    最简单的方法是通过利用对象可序列化进行克隆。 Apache Commons提供了一种执行此操作的方法,但是为了完整起见,下面也是您自己执行此操作的代码。

    @SuppressWarnings("unchecked")
    public static  T cloneThroughSerialize(T t) throws Exception {
       ByteArrayOutputStream bos = new ByteArrayOutputStream();
       serializeToOutputStream(t, bos);
       byte[] bytes = bos.toByteArray();
       ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
       return (T)ois.readObject();
    }
    
    private static void serializeToOutputStream(Serializable ser, OutputStream os)
                                                              throws IOException {
       ObjectOutputStream oos = null;
       try {
          oos = new ObjectOutputStream(os);
          oos.writeObject(ser);
          oos.flush();
       } finally {
          oos.close();
       }
    }
    
    // using our custom method
    Object cloned = cloneThroughSerialize (someObject);
    
    // or with Apache Commons
    cloned = org.apache.commons.lang. SerializationUtils.clone(someObject);

    但是,如果我们要克隆的类不是可序列化的,并且我们无法控制源代码或者无法将其设置为可序列化该怎么办?

    选项1 – Java深度克隆库

    有一个不错的小程序库,它可以深度克隆几乎所有Java对象- 克隆 它利用Java的出色反射功能来提供优化的对象的深克隆版本。

    Cloner cloner=new Cloner();
    Object cloned = cloner.deepClone(someObject);

    如您所见,它非常简单有效,并且需要最少的代码。 除了这个简单的示例,它还具有一些更高级的功能,您可以在此处查看

    选项2 – JSON克隆

    如果我们无法将新库引入我们的代码库,该怎么办? 我们中有些人处理批准程序以引入新的库,对于一个简单的用例,可能不值得。

    好吧,只要我们有某种方式可以序列化和还原对象,就可以进行深层复制。 JSON通常被使用,因此它是一个很好的选择,因为我们大多数人都使用一个或另一个JSON库。

    Java中的大多数JSON库都可以有效地序列化任何POJO,而无需任何配置或映射。 这意味着,如果您具有JSON库并且不能或不会引入更多库来提供深度克隆,则可以利用现有的JSON库来获得相同的效果。 请注意,此方法将比其他方法慢,但是对于绝大多数应用程序,这不会引起任何性能问题。

    以下是使用GSON库的示例。

    @SuppressWarnings("unchecked")
    public static  T cloneThroughJson(T t) {
       Gson gson = new Gson();
       String json = gson.toJson(t);
       return (T) gson.fromJson(json, t.getClass());
    }
    // ...
    Object cloned = cloneThroughJson(someObject);

    请注意,仅当复制的对象具有默认的无参数构造函数时,这才可能起作用。 对于GSON,您可以使用实例创建者来解决此问题。 其他框架具有类似的概念,因此如果遇到无法修改的类且没有默认构造函数的问题,则可以使用该框架。


    结论

    我建议做的一件事是,对于需要克隆的任何类,都应该添加一些单元测试,以确保一切正常。 这可以防止对类的更改(例如,升级库版本)在您不知情的情况下破坏应用程序,尤其是在您设置了持续集成环境的情况下。

    我概述了几种在没有任何自定义代码的情况下克隆对象的方法。 如果您使用其他任何方法获得相同的结果,请分享。

    参考: Carfey Software Blog上的JCG合作伙伴 Craig Flichel从Java轻松深度克隆了Java中的可序列化和不可序列化的对象

    相关文章 :


    翻译自: https://www.javacodegeeks.com/2011/12/cloning-of-serializable-and-non.html

    java序列化深克隆

    展开全文
  • 【运行结果】:【运行结果】姓名:rollen年龄:20姓名:hello world年龄:100姓名:hello world年龄:100下面看看java中的浅拷贝对于类中的每个域,如果只包含基本类型或者不可变的引用类型,如String,或者对象在其...

    先用一个例子来说明假克隆吧,也就是用“=”之后的效果、。

    【运行结果】:

    【运行结果】

    姓名:rollen年龄:20

    姓名:hello world年龄:100

    姓名:hello world年龄:100

    下面看看java中的浅拷贝

    对于类中的每个域,如果只包含基本类型或者不可变的引用类型,如String,或者对象在其生命周期内不会发生变化,则可以使用浅拷贝来复制对象,但是一般使用深拷贝。

    【运行结果】:

    克隆之前:

    name:rollen, age:20

    Address: state:中国munber: 1

    克隆之后

    name:rollen, age:20

    Address: state:美国munber: 2

    -----

    name:hello world, age:100

    Address: state:美国munber: 2

    但是上面的主函数中的:

    替换为:

    运行结果为:

    克隆之前:

    name:rollen, age:20

    Address: number: 1state中国

    克隆之后

    name:rollen, age:20

    Address: number: 1state中国

    -----

    name:hello world, age:100

    Address: number: 2state美国

    这里我有点不明白了,为什么这种情况下克隆之后两个address会不一样呢?

    谁帮忙指点一下,谢谢了、

    现在看看java对象的深克隆

    【运行结果】:

    【运行结果】:

    克隆之前:

    name:rollen, age:20

    Address: state:中国munber: 1

    克隆之后

    name:rollen, age:20

    Address: state:中国munber: 1

    -----

    name:hello world, age:100

    Address: state:美国munber: 2

    序列化接口和对象克隆

    【运行结果】:

    克隆之前:

    name:rollen, age:20

    Address: number: 1state中国

    克隆之后

    name:rollen, age:20

    Address: number: 1state中国

    -----

    name:hello world, age:100

    Address: number: 2state美国

    对于任何一个序列化的对象,都必须要求实现Serializable接口。其次,如果这个类的域中也有引用对象,则也有要求这个引用类型也实现这个接口,。最后,序列化方式实现克隆效率不高,没有直接深度克隆的效率高。有兴趣的朋友可以测试一下。

    展开全文
  • 简述:用字节流的方式,复制Java对象代码:流克隆复制函数public static Object deepClone(Object obj){if(obj == null){return null;}try {ByteArrayOutputStream byteOut = new ByteArrayOutputStream();Object ...

    简述:

    用字节流的方式,复制Java对象

    代码:

    流克隆复制函数

    public static Object deepClone(Object obj){

    if(obj == null){

    return null;

    }

    try {

    ByteArrayOutputStream byteOut = new ByteArrayOutputStream();

    Object cloneObj = null;

    ObjectOutputStream out = new ObjectOutputStream(byteOut);

    out.writeObject(obj);

    ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());

    ObjectInputStream in = new ObjectInputStream(byteIn);

    cloneObj = in.readObject();

    return cloneObj;

    } catch (Exception e) {

    throw new RuntimeException(e);

    }

    }

    ObjectClone.java

    package test;

    import java.io.ByteArrayInputStream;

    import java.io.ByteArrayOutputStream;

    import java.io.ObjectInputStream;

    import java.io.ObjectOutputStream;

    import java.io.Serializable;

    public class ObjectClone {

    /**

    * 测试对象

    */

    private static class Person implements Serializable {

    private String name;

    private int age;

    Person(String name, int age){

    this.name = name;

    this.age = age;

    }

    @Override

    public String toString() {

    return String.format("name: %s\nage: %s", name, age);

    }

    }

    /**

    * 测试函数

    */

    public static void main(String[] args) {

    Person person = new Person("Henry", 22);

    Person newPerson = (Person)ObjectClone.deepClone(person);

    System.out.println(newPerson);

    }

    /**

    * 工具类

    *

    * @param obj

    * @return

    */

    public static Object deepClone(Object obj){

    if(obj == null){

    return null;

    }

    try {

    ByteArrayOutputStream byteOut = new ByteArrayOutputStream();

    Object cloneObj = null;

    ObjectOutputStream out = new ObjectOutputStream(byteOut);

    out.writeObject(obj);

    ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());

    ObjectInputStream in = new ObjectInputStream(byteIn);

    cloneObj = in.readObject();

    return cloneObj;

    } catch (Exception e) {

    throw new RuntimeException(e);

    }

    }

    }

    测试结果:

    0818b9ca8b590ca3270a3433284dd417.png

    展开全文
  • 先用一个例子来说明假克隆吧,也就是用“=”之后的效果、。public class Employee{public Employee(){}public Employee(String name, int age){this.age = age;this.name = name;}@Overridepublic String toString()...

    先用一个例子来说明假克隆吧,也就是用“=”之后的效果、。

    public class Employee{

    public Employee(){

    }

    public Employee(String name, int age){

    this.age = age;

    this.name = name;

    }

    @Override

    public String toString(){

    return "姓名: " + name + "年龄: " + age;

    }

    public String getName(){

    return name;

    }

    public void setName(String name){

    this.name = name;

    }

    public int getAge(){

    return age;

    }

    public void setAge(int age){

    this.age = age;

    }

    public static void main(String[] args){

    Employee demo1 = new Employee("rollen", 20);

    System.out.println(demo1);

    Employee demo2 = demo1;

    demo2.setAge(100);

    demo2.setName("hello world");

    System.out.println(demo1);

    System.out.println(demo2);

    }

    private String name;

    private int age;

    }

    【运行结果】:

    【运行结果】

    姓名:rollen年龄:20

    姓名:hello world年龄:100

    姓名:hello world年龄:100

    下面看看java中的浅拷贝

    对于类中的每个域,如果只包含基本类型或者不可变的引用类型,如String,或者对象在其生命周期内不会发生变化,则可以使用浅拷贝来复制对象,但是一般使用深拷贝。

    class Address{

    public Address(){

    }

    public Address(String state, int number){

    this.number = number;

    this.state = state;

    }

    @Override

    public String toString(){

    return "state: " + state + " munber: " + number;

    }

    public String getState(){

    return state;

    }

    public void setState(String state){

    this.state = state;

    }

    public int getNumber(){

    return number;

    }

    public void setNumber(int number){

    this.number = number;

    }

    private String state;

    private int number;

    }

    public class Employee implements Cloneable{

    public Employee(){

    }

    public Employee(String name, int age, Address address){

    this.address = address;

    this.age = age;

    this.name = name;

    }

    public String getName(){

    return name;

    }

    public void setName(String name){

    this.name = name;

    }

    public int getAge(){

    return age;

    }

    public void setAge(int age){

    this.age = age;

    }

    public Address getAddress(){

    return address;

    }

    public void setAddress(Address address){

    this.address = address;

    }

    @Override

    public String toString(){

    StringBuilder sb = new StringBuilder();

    sb.append("name:" + name + ", ");

    sb.append("age:" + age + " \n");

    sb.append("Address: " + address);

    return sb.toString();

    }

    @Override

    protected Employee clone(){

    Employee employee = null;

    try{

    employee = (Employee) super.clone();

    }catch(CloneNotSupportedException e){

    e.printStackTrace();

    }

    return employee;

    }

    public static void main(String[] args){

    System.out.println("克隆之前:");

    Address add1 = new Address("中国", 1);

    Employee emp1 = new Employee("rollen", 20, add1);

    System.out.println(emp1);

    System.out.println("克隆之后");

    Employee emp2 = emp1.clone();

    emp2.setName("hello world");

    emp2.setAge(100);

    emp2.address.setNumber(2);

    emp2.address.setState("美国");

    System.out.println(emp1);

    System.out.println("-----");

    System.out.println(emp2);

    }

    private String name;

    private int age;

    private Address address;

    }

    【运行结果】:

    克隆之前:

    name:rollen, age:20

    Address: state:中国munber: 1

    克隆之后

    name:rollen, age:20

    Address: state:美国munber: 2

    -----

    name:hello world, age:100

    Address: state:美国munber: 2

    但是上面的主函数中的:

    // emp2.address.setNumber(2);

    // emp2.address.setState("美国");

    替换为:

    emp2.setAddress(new Address("美国", 2));

    运行结果为:

    克隆之前:

    name:rollen, age:20

    Address: number: 1state中国

    克隆之后

    name:rollen, age:20

    Address: number: 1state中国

    -----

    name:hello world, age:100

    Address: number: 2state美国

    这里我有点不明白了,为什么这种情况下克隆之后两个address会不一样呢?

    谁帮忙指点一下,谢谢了、

    现在看看java对象的深克隆

    class Address implements Cloneable{

    public Address(){

    }

    public Address(String state, int number){

    this.number = number;

    this.state = state;

    }

    @Override

    public String toString(){

    return "state: " + state + " munber: " + number;

    }

    @Override

    protected Address clone() throws CloneNotSupportedException{

    Address address = null;

    address = (Address) super.clone();

    return address;

    }

    public String getState(){

    return state;

    }

    public void setState(String state){

    this.state = state;

    }

    public int getNumber(){

    return number;

    }

    public void setNumber(int number){

    this.number = number;

    }

    private String state;

    private int number;

    }

    public class Employee implements Cloneable{

    public Employee(){

    }

    public Employee(String name, int age, Address address){

    this.address = address;

    this.age = age;

    this.name = name;

    }

    public String getName(){

    return name;

    }

    public void setName(String name){

    this.name = name;

    }

    public int getAge(){

    return age;

    }

    public void setAge(int age){

    this.age = age;

    }

    public Address getAddress(){

    return address;

    }

    public void setAddress(Address address){

    this.address = address;

    }

    @Override

    public String toString(){

    StringBuilder sb = new StringBuilder();

    sb.append("name:" + name + ", ");

    sb.append("age:" + age + " \n");

    sb.append("Address: " + address);

    return sb.toString();

    }

    @Override

    protected Employee clone(){

    Employee employee = null;

    try{

    employee = (Employee) super.clone();

    employee.address = address.clone();}catch(CloneNotSupportedException e){

    e.printStackTrace();

    }

    return employee;

    }

    public static void main(String[] args){

    System.out.println("克隆之前:");

    Address add1 = new Address("中国", 1);

    Employee emp1 = new Employee("rollen", 20, add1);

    System.out.println(emp1);

    System.out.println("克隆之后");

    Employee emp2 = emp1.clone();

    emp2.setName("hello world");

    emp2.setAge(100);

    emp2.setAddress(new Address("美国", 2));

    System.out.println(emp1);

    System.out.println("-----");

    System.out.println(emp2);

    }

    private String name;

    private int age;

    private Address address;

    }

    【运行结果】:

    【运行结果】:

    克隆之前:

    name:rollen, age:20

    Address: state:中国munber: 1

    克隆之后

    name:rollen, age:20

    Address: state:中国munber: 1

    -----

    name:hello world, age:100

    Address: state:美国munber: 2

    序列化接口和对象克隆

    import java.io.ByteArrayInputStream;

    import java.io.ByteArrayOutputStream;

    import java.io.ObjectInputStream;

    import java.io.ObjectOutputStream;

    import java.io.Serializable;

    class Address implements Serializable{

    public Address(){

    }

    public Address(String state, int number){

    this.number = number;

    this.state = state;

    }

    @Override

    public String toString(){

    StringBuilder sb = new StringBuilder();

    sb.append("number: " + number);

    sb.append("state" + state + "\n");

    return sb.toString();

    }

    public String getState(){

    return state;

    }

    public void setState(String state){

    this.state = state;

    }

    public int getNumber(){

    return number;

    }

    public void setNumber(int number){

    this.number = number;

    }

    private String state;

    private int number;

    }

    public class Employee implements Cloneable, Serializable{

    public Employee(){

    }

    public Employee(String name, int age, Address address){

    this.address = address;

    this.age = age;

    this.name = name;

    }

    public String getName(){

    return name;

    }

    public void setName(String name){

    this.name = name;

    }

    public int getAge(){

    return age;

    }

    public void setAge(int age){

    this.age = age;

    }

    public Address getAddress(){

    return address;

    }

    public void setAddress(Address address){

    this.address = address;

    }

    @Override

    public String toString(){

    StringBuilder sb = new StringBuilder();

    sb.append("name:" + name + ", ");

    sb.append("age:" + age + " \n");

    sb.append("Address: " + address);

    return sb.toString();

    }

    @Override

    protected Employee clone(){

    Employee employee = null;

    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    try{

    ObjectOutputStream oos = new ObjectOutputStream(baos);

    oos.writeObject(this);

    oos.close();

    ByteArrayInputStream bais = new ByteArrayInputStream(

    baos.toByteArray());

    ObjectInputStream ois = new ObjectInputStream(bais);

    employee = (Employee) ois.readObject();

    ois.close();

    }catch(Exception e){

    e.printStackTrace();

    }

    return employee;

    }

    public static void main(String[] args){

    System.out.println("克隆之前:");

    Address add1 = new Address("中国", 1);

    Employee emp1 = new Employee("rollen", 20, add1);

    System.out.println(emp1);

    System.out.println("克隆之后");

    Employee emp2 = emp1.clone();

    emp2.setName("hello world");

    emp2.setAge(100);

    emp2.address.setNumber(2);

    emp2.address.setState("美国");

    System.out.println(emp1);

    System.out.println("-----");

    System.out.println(emp2);

    }

    private String name;

    private int age;

    private Address address;

    }

    【运行结果】:

    克隆之前:

    name:rollen, age:20

    Address: number: 1state中国

    克隆之后

    name:rollen, age:20

    Address: number: 1state中国

    -----

    name:hello world, age:100

    Address: number: 2state美国

    对于任何一个序列化的对象,都必须要求实现Serializable接口。其次,如果这个类的域中也有引用对象,则也有要求这个引用类型也实现这个接口,。最后,序列化方式实现克隆效率不高,没有直接深度克隆的效率高。有兴趣的朋友可以测试一下。

    展开全文
  • Object类的clone()方法浅克隆//浅克隆/** 1.Object类中的clone()方法为protected的* 2.需要实现克隆功能的类必须实现Cloneable接口* */class Kid{public int age = 10;}class Person implements Cloneable{public ...
  • java序列化克隆 在我以前的文章中,我解释了深度克隆和浅层克隆之间的区别 , 以及复制构造函数和防御性复制方法比默认的Java克隆如何更好。 使用复制构造函数和防御性复制方法进行的Java对象克隆当然具有某些...
  • 编写我们的实验代码,该代码用于实现我们的一个克隆实例,具体如下图所示,代码如下:public static void main(String[] args) {System.out.println("序列化之前");Address address=new Address("中国","吉林","长春...
  • 我们知道,在java中,将一个非原型类型类型的对象引用,赋值给另一个对象的引用之后,这两个引用就指向了同一个对象,如:public class DeepCloneTest {private class CloneTest {private Long myLong = new Long(1)...
  • Java序列化克隆

    2013-04-18 13:52:33
    Java序列化克隆 2011-03-04 09:25 mojianpo JavaEye博客 我要评论(1) 字号:T | T 本篇文章主要对Java序列化来讲解,Java 序列化技术可以使你将一个对象的状态写入一个Byte 流里,并且可以从...
  • 1、java序列化 序列化介绍: 序列化:将java对象写入字节流;反序列化:从字节流中恢复对象 意义:序列化机制允许将实现序列化的java对象装换位字节序列,这些字节序列可以保存在磁盘,数据库上,或者通过网络...
  • Java 序列化技术可以使你将一个对象的状态写入一个Byte 流里,并且可以从其它地方把该Byte 流里的数据读出来,重新构造一个相同的对象。 当两个进程在进行远程通信时,彼此可以发送各种类型的数据。无论是何种...
  • java 序列化和反序列化实现克隆

    千次阅读 2016-11-13 12:55:50
    package com.clone.test; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; pu
  • 一、序列化和反序列化的概念  把对象转换为字节序列的过程称为对象的序列化。  把字节序列恢复为对象的过程称为对象的反序列化。  对象的序列化主要有两种用途:  1) 把对象的字节序列永久地保存到硬盘上,通常...
  • Java序列化克隆--对象深度拷贝

    千次阅读 2013-10-03 11:48:14
    Java序列化克隆--对象...Java序列化克隆 序列化   Java 序列化技术可以使你将一个对象的状态写入一个Byte 流里,并且可以从其它地方把该Byte 流里的数据读出来,重新构造一个相同的对象。   当两个进
  • 序列化克隆 → 推荐:《刀剑神域-序列之争》 序列化序列化 serialversionUID 作用 IDEA配置警告 序列化中常见的两类异常 java.io.NotSerializableException java.io.InvalidClassException 克隆克隆...
  • java序列化深度克隆

    2012-08-21 09:06:10
    publicObject copy() throwsIOException, ... //将对象序列化后写在流里,因为写在流里面的对象是一份拷贝,  //原对象仍然在JVM里  ByteArrayOutputStream bos = newByteArrayOutputStream();
  • 序列化作用:  1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;  2) 在网络上传送对象的字节序列。  在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便...
  • Serializable接口 序列化:对象的寿命通常随着生成...Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类...
  • 本篇博客内容:ObjectOutputStream + 内存流ByteArrayOutputStreamObjectOutputStream + FileOutputStream一、浅克隆(ShallowClone)和深克隆(DeepClone) <=返回目录1.1、浅克隆和深克隆区别packagecom.oy....
  • java序列化与深度克隆

    2014-03-31 15:18:25
    如果类的成员变量比较复杂,例如引用了...可以考虑序列化的方法完成克隆 test代码 package com.mingrisoft; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.Fil
  • java通过对象序列化和反序列化实现克隆总结 在JAVA中,我们想要实现对一个对象的克隆主要有两种方式 实现Cloneable接口并重写clone()方法; 实现Serializable接口,然后通过对象的序列化和反序列化操作实现真正的...
  • Java 序列化方式实现深克隆

    千次阅读 2017-10-09 12:22:14
    // 用序列化与反序列化实现深克隆 private Object deepClone(Object src) { Object o = null; try { if (src != null) { ByteArrayOutputStream baos = new B
  • Java序列化方式深克隆

    2018-01-18 08:48:38
    public static Object copyOfDeep(Object obj){ ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(obj);...
  • java序列化

    2020-11-20 22:29:45
    如何将一个 java 对象序列化到文件里如何实现对象克隆? 什么是 java 序列化,如何实现 java 序列化序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写...
  • java 序列化实现深度克隆

    千次阅读 2015-01-29 10:16:47
    import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import j

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 999
精华内容 399
关键字:

java序列化克隆

java 订阅