首页 > 编程语言 >java基础-序列化和拷贝

java基础-序列化和拷贝

时间:2023-04-09 12:33:28浏览次数:53  
标签:Java 对象 clone 类型 java 拷贝 序列化

1.序列化

1.1.定义

如果我们需要持久化Java对象,或者在⽹络传输Java对象,这些场景都需要⽤到序列化,简单来说序列化就是将数据结构或对象转换成⼆进制字节流的过程,反序列化就是将在序列化过程中所⽣成的⼆进制字节流转换成数据结构或者对象的过程

对于Java这种⾯向对象编程语⾔来说,我们序列化的都是对象,保存的是对象的状态,即它的成员变量,因此不会关注类中的变量

Serializable实现序列化

在Java中,只要一个类实现了java.io.Serializable接口,那么它就可以被序列化,在类中增加writeObject和readObject方法可以实现自定义序列化策略

虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类的序列化ID是否一致(就是private static final long serialVersionUID)

transient

如果有些字段不想进⾏序列化怎么办?对于不想进⾏序列化的变量,使⽤transient关键字修饰

transient关键字的作⽤是阻⽌实例中那些⽤此关键字修饰的的变量序列化,当对象被反序列化时,被transient修饰的变量值会被设置为初始值,如int为0,对象为null,transient只能修饰变量,不能修饰类和⽅法

序列化评价指标

性能及效率:指将一个对象序列化所花费的时间

空间开销:指的是序列化对象后所占用的空间

安全性:如果安全性存在问题,则容易被攻击入侵

通用性和兼容性:是否支持跨语言、跨平台

1.2.序列化比较

1.2.1.jdk序列化

不支持跨语言,性能差,序列化后的对象较大

1.2.2.jackson序列化

1.2.3.protobuf序列化

protobuf的一个缺点是要编写.proto格式的配置文件,由于java具有反射和动态代码生成的能力,这个预编译过程不是必须的,可以在代码执行时来实现,protostuff已经实现了这个功能

具体细节可以参考:https://zhuanlan.zhihu.com/p/537871378

1.2.4.kryo序列化

类注册机制:可以将类全路径名替换为数字,但数字的分配与注册顺序相关,所以序列化和反序列化的时候要确保注册顺序一致,对于对象类型的序列化,需要将对象类型和对象内部field的类型都注册

节省空间:对于值来说,int和long用可变长度编码,string取消了长度字段,用特殊符号记录string结束;类型利用类注册机制用数字替代全限定名

序列化过程:先序列化类型,再序列化该类型的值,如果自定义类型,例如(cn.uce.demo.Student),也是先类型再值的模式,只不过值是一个字段一个字段的递归进行

循环依赖:引入了对象图的概念来消除循环依赖的序列化,已序列化的对象,在循环引用时只是用一个int类型来表示该对象值,否则的话,循环引用可能会导致栈溢出

非线程安全:kryo实例非线程安全是因为完成一次写入后,需要重置Kryo中的临时数据结构(包括注册类型,序列化上下文,序列化过程中使用的缓存),可以用ThreadLocal来解决线程安全

2.拷贝

2.1.定义

一共有三种方式,第一种方式是引用拷贝,第二种方式是浅拷贝,第三种是深拷贝

引用拷贝

在Java中,A a1 = a2,我们需要理解的是这实际上复制的是引用,也就是说a1和a2指向的是同一个对象。因此当a1变化的时候,a2里面的成员变量也会跟着变化

浅复制

浅拷贝会在堆上创建一个新的对象,不过如果原对象内部的属性是引用类型的话,浅拷贝会直接复制内部对象的引用地址,也就是说拷贝对象和原对象共用同一个内部对象

 

class Resume implements Cloneable{
    public Object clone() {
    	try {
    		return (Resume)super.clone();
        } catch (Exception e) {
    		e.printStackTrace();
            return null;
    	}
    }
}

深复制

深拷贝会完全复制整个对象,包括这个对象所包含的内部对象

class Student implements Cloneable {
	String name;
	int age;
    Professor p;
	Student(String name, int age, Professor p) {
        this.name = name;
		this.age = age;
        this.p = p;
    }
	public Object clone() {
        Student o = null;
        try {
			o = (Student) super.clone();
		} catch (CloneNotSupportedException e) {
            System.out.printIn(e.toString());
        }
		o.p = (Professor) p.clone();
		return o;
    }
}

也可以使用序列化,在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里,再从流里读出来,便可以重建对象

 

 

标签:Java,对象,clone,类型,java,拷贝,序列化
From: https://www.cnblogs.com/zz-coding/p/17300132.html

相关文章

  • Java生成PDF几种方式
    ##1、itextPDF直接填充<!--PDF工具类--><dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13</version></dependency>......
  • java基础-代理
    1.代理简介2.静态代理3.动态代理3.1.jdk使用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理,JDK创建代理对象效率较高,但是执行效率较低使用流程:实现InvocationHandler接口,重写invoke(),使用Proxy.newProxyInstance()产生代理对象,被代理的对象......
  • 剑指offer05(Java)-替换空格(简单)
    题目:请实现一个函数,把字符串s中的每个空格替换成"%20"。 示例1:输入:s="Wearehappy."输出:"We%20are%20happy." 限制:0<=s的长度<=10000来源:力扣(LeetCode)链接:https://leetcode.cn/problems/ti-huan-kong-ge-lcof著作权归领扣网络所有。商业转载请联系官方授权,......
  • java基础-反射
    1.反射定义反射机制是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法,并且对于任意一个对象,都能够调用它的任意一个方法,这种动态获取信息以及动态调用对象方法的功能称为Java反射机制动态语言定义:动态语言是指程序在运行时可以改变其结构,新的函数可以引进,已有的......
  • java基础知识合集-io
    1.IO简介2.IO分类2.1.流分类按照流的流向分,可以分为输入流和输出流按照操作单元划分,可以划分为字节流和字符流按照流的角色划分为节点流和处理流JavalO流共涉及40多个类,这些类看上去很杂乱,但实际上很有规则,而且彼此之间存在紧密的联系,JavalO流的40多个类都是从如下4个抽......
  • C++逆向分析——对象拷贝
    对象拷贝我们通常存储对象,都用数组、列表之类的来存储,那如下所示我们使用数组来存储对象,但是在工作中发现这个数组不够用了,就需要一个更大的数据,但我们重新创建一个数组还需要把原来的数据复制过来;在C语言中可以使用函数来进行拷贝,直接拷贝内存,在C++中实际上跟C语言要做的事情是......
  • Java标准类
    Java标准类标准类的定义类的代码publicclassPerson{/*标准类:1.所有成员变量都用private修饰2.每个成员变量都有一个getter,setter方法3.一个无参构造方法4.一个全参构造方法这样的标准类也叫JavaBean*/privateStringn......
  • java中操作redis
             ......
  • Java SpringBoot Bean InitializingBean
    Spring中有两种类型的Bean,一种是普通Bean,另一种是工厂Bean,即FactoryBean。工厂Bean跟普通Bean不同,其返回的对象不是指定类的一个实例,其返回的是该工厂Bean的getObject方法所返回的对象。Spring初始化bean有两种方式:实现InitializingBean接口,实现afterPropertiesSet方法。(比通过反射......
  • Java SpringBoot Test 单元测试中包括多线程时,没跑完就结束了
    如何阻止JavaSpringBootTest单元测试中包括多线程时,没跑完就结束了使用CountDownLatchCountDownLatch、CyclicBarrier使用区别多线程ThreadPoolTaskExecutor应用JavaBasePooledObjectFactory对象池化技术@SpringBootTestpublicclassPoolTest{@Testvoid......