全方位解析Java的序列化

揭开Java序列化的神秘面纱(上)Serializable使用详解 自定义序列化逻辑允许开发者控制对象序列化和反序列化的详细过程。在Java中,可以通过重写对象类的和readObject方法来实现自定义序列化。这对于优化性能、处理非可序列化对象、实现版本控制或添加额外的逻辑非常有用。第一步,重写方法这个方法是在对象序列化时被调用的。可以在这里添加自定义的序列化逻辑,比如只序列化对象的某些字段,或者在序列化之前进行某些计算或检查。第二步,重写readObject方法这个方法是在对象反序列化时被调用的。 阅读详情

前言

相信大家日常开发中,经常看到Java对象“implements Serializable”。那么,它到底有什么用呢?本文从以下几个角度来解析序列这一块知识点~

  • 什么是Java序列化?
  • 为什么需要序列化?
  • 序列化用途
  • Java序列化常用API
  • 序列化的使用
  • 序列化底层
  • 日常开发序列化的注意点
  • 序列化常见面试题

一、什么是Java序列化?

  • 序列化:把Java对象转换为字节序列的过程
  • 反序列:把字节序列恢复为Java对象的过程

二、为什么需要序列化?

Java对象是运行在JVM的堆内存中的,如果JVM停止后,它的生命也就戛然而止。

如果想在JVM停止后,把这些对象保存到磁盘或者通过网络传输到另一远程机器,怎么办呢?磁盘这些硬件可不认识Java对象,它们只认识二进制这些机器语言,所以我们就要把这些对象转化为字节数组,这个过程就是序列化啦~

打个比喻,作为大城市漂泊的码农,搬家是常态。当我们搬书桌时,桌子太大了就通不过比较小的门,因此我们需要把它拆开再搬过去,这个拆桌子的过程就是序列化。 而我们把书桌复原回来(安装)的过程就是反序列化啦。

三、序列化用途

序列化使得对象可以脱离程序运行而独立存在,它主要有两种用途:

  • 1) 序列化机制可以让对象地保存到硬盘上,减轻内存压力的同时,也起了持久化的作用;

比如 Web服务器中的Session对象,当有 10+万用户并发访问的,就有可能出现10万个Session对象,内存可能消化不良,于是Web容器就会把一些seesion先序列化到硬盘中,等要用了,再把保存在硬盘中的对象还原到内存中。

  • 2) 序列化机制让Java对象在网络传输不再是天方夜谭。

我们在使用Dubbo远程调用服务框架时,需要把传输的Java对象实现Serializable接口,即让Java对象序列化,因为这样才能让对象在网络上传输。

四、Java序列化常用API

java.io.ObjectOutputStream
java.io.ObjectInputStream
java.io.Serializable
java.io.Externalizable
Serializable 接口

Serializable接口是一个标记接口,没有方法或字段。一旦实现了此接口,就标志该类的对象就是可序列化的。

public interface Serializable {
}
Externalizable 接口

Externalizable继承了Serializable接口,还定义了两个抽象方法:writeExternal()和readExternal(),如果开发人员使用Externalizable来实现序列化和反序列化,需要重写writeExternal()和readExternal()方法

public interface Externalizable extends java.io.Serializable {
    void writeExternal(ObjectOutput out) throws IOException;
    void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
}
java.io.ObjectOutputStream类

表示对象输出流,它的writeObject(Object obj)方法可以对指定obj对象参数进行序列化,再把得到的字节序列写到一个目标输出流中。

java.io.ObjectInputStream

表示对象输入流,它的readObject()方法,从输入流中读取到字节序列,反序列化成为一个对象,最后将其返回。

五、序列化的使用

序列化如何使用?来看一下,序列化的使用的几个关键点吧:

  • 声明一个实体类,实现Serializable接口
  • 使用ObjectOutputStream类的writeObject方法,实现序列化
  • 使用ObjectInputStream类的readObject方法,实现反序列化
声明一个Student类,实现Serializable
public class Student implements Serializable {

    private Integer age;
    private String name;

    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
使用ObjectOutputStream类的writeObject方法,对Student对象实现序列化

把Student对象设置值后,写入一个文件,即序列化,哈哈~

ObjectOutputStream objectOutputStream = new ObjectOutputStream( new FileOutputStream("D:\\text.out"));
Student student = new Student();
student.setAge(25);
student.setName("jayWei");
objectOutputStream.writeObject(student);

objectOutputStream.flush();
objectOutputStream.close();

看看序列化的可爱模样吧,test.out文件内容如下(使用UltraEdit打开):

使用ObjectInputStream类的readObject方法,实现反序列化,重新生成student对象

再把test.out文件读取出来,反序列化为Student对象

ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\text.out"));
Student student = (Student) objectInputStream.readObject();
System.out.println("name="+student.getName());

六、序列化底层

Serializable底层

Serializable接口,只是一个空的接口,没有方法或字段,为什么这么神奇,实现了它就可以让对象序列化了?

public interface Serializable {
}

为了验证Serializable的作用,把以上demo的Student对象,去掉实现Serializable接口,看序列化过程怎样吧~

序列化过程中抛出异常啦,堆栈信息如下:

Exception in thread "main" java.io.NotSerializableException: com.example.demo.Student
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
	at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
	at com.example.demo.Test.main(Test.java:13)

顺着堆栈信息看一下,原来有重大发现,如下~

原来底层是这样:ObjectOutputStream 在序列化的时候,会判断被序列化的Object是哪一种类型,String?array?enum?还是 Serializable,如果都不是的话,抛出 NotSerializableException异常。所以呀,Serializable真的只是一个标志,一个序列化标志~

writeObject(Object)

序列化的方法就是writeObject,基于以上的demo,我们来分析一波它的核心方法调用链吧~(建议大家也去debug看一下这个方法,感兴趣的话)

writeObject直接调用的就是writeObject0()方法,

public final void writeObject(Object obj) throws IOException {
    ......
    writeObject0(obj, false);
    ......
}

writeObject0 主要实现是对象的不同类型,调用不同的方法写入序列化数据,这里面如果对象实现了Serializable接口,就调用writeOrdinaryObject()方法~

private void writeObject0(Object obj, boolean unshared)
        throws IOException
    {
    ......
   //String类型
    if (obj instanceof String) {
        writeString((String) obj, unshared);
   //数组类型
    } else if (cl.isArray()) {
        writeArray(obj, desc, unshared);
   //枚举类型
    } else if (obj instanceof Enum) {
        writeEnum((Enum<?>) obj, desc, unshared);
   //Serializable实现序列化接口
    } else if (obj instanceof Serializable) {
        writeOrdinaryObject(obj, desc, unshared);
    } else{
        //其他情况会抛异常~
        if (extendedDebugInfo) {
            throw new NotSerializableException(
                cl.getName() + "\n" + debugInfoStack.toString());
        } else {
            throw new NotSerializableException(cl.getName());
        }
    }
    ......

writeOrdinaryObject()会先调用writeClassDesc(desc),写入该类的生成信息,然后调用writeSerialData方法,写入序列化数据

    private void writeOrdinaryObject(Object obj,
                                     ObjectStreamClass desc,
                                     boolean unshared)
        throws IOException
    {
            ......
            //调用ObjectStreamClass的写入方法
            writeClassDesc(desc, false);
            // 判断是否实现了Externalizable接口
            if (desc.isExternalizable() && !desc.isProxy()) {
                writeExternalData((Externalizable) obj);
            } else {
                //写入序列化数据
                writeSerialData(obj, desc);
            }
            .....
    }

writeSerialData()实现的就是写入被序列化对象的字段数据

  private void writeSerialData(Object obj, ObjectStreamClass desc)
        throws IOException
    {
        for (int i = 0; i < slots.length; i++) {
            if (slotDesc.hasWriteObjectMethod()) {
                   //如果被序列化的对象自定义实现了writeObject()方法,则执行这个代码块
                    slotDesc.invokeWriteObject(obj, this);
            } else {
                // 调用默认的方法写入实例数据
                defaultWriteFields(obj, slotDesc);
            }
        }
    }

defaultWriteFields()方法,获取类的基本数据类型数据,直接写入底层字节容器;获取类的obj类型数据,循环递归调用writeObject0()方法,写入数据~

   private void defaultWriteFields(Object obj, ObjectStreamClass desc)
        throws IOException
    {   
        // 获取类的基本数据类型数据,保存到primVals字节数组
        desc.getPrimFieldValues(obj, primVals);
        //primVals的基本类型数据写到底层字节容器
        bout.write(primVals, 0, primDataSize, false);

        // 获取对应类的所有字段对象
        ObjectStreamField[] fields = desc.getFields(false);
        Object[] objVals = new Object[desc.getNumObjFields()];
        int numPrimFields = fields.length - objVals.length;
        // 获取类的obj类型数据,保存到objVals字节数组
        desc.getObjFieldValues(obj, objVals);
        //对所有Object类型的字段,循环
        for (int i = 0; i < objVals.length; i++) {
            ......
              //递归调用writeObject0()方法,写入对应的数据
            writeObject0(objVals[i],
                             fields[numPrimFields + i].isUnshared());
            ......
        }
    }

七、日常开发序列化的一些注意点

  • static静态变量和transient 修饰的字段是不会被序列化的
  • serialVersionUID问题
  • 如果某个序列化类的成员变量是对象类型,则该对象类型的类必须实现序列化
  • 子类实现了序列化,父类没有实现序列化,父类中的字段丢失问题
static静态变量和transient 修饰的字段是不会被序列化的

static静态变量和transient 修饰的字段是不会被序列化的,我们来看例子分析一波~ Student类加了一个类变量gender和一个transient修饰的字段specialty

public class Student implements Serializable {

    private Integer age;
    private String name;

    public static String gender = "男";
    transient  String specialty = "计算机专业";

    public String getSpecialty() {
        return specialty;
    }

    public void setSpecialty(String specialty) {
        this.specialty = specialty;
    }

    @Override
    public String toString() {
        return "Student{" +"age=" + age + ", name='" + name + '\'' + ", gender='" + gender + '\'' + ", specialty='" + specialty + '\'' +
                '}';
    }
    ......

打印学生对象,序列化到文件,接着修改静态变量的值,再反序列化,输出反序列化后的对象~

运行结果:

序列化前Student{age=25, name='jayWei', gender='男', specialty='计算机专业'}
序列化后Student{age=25, name='jayWei', gender='女', specialty='null'}

对比结果可以发现:

  • 1)序列化前的静态变量性别明明是‘男’,序列化后再在程序中修改,反序列化后却变成‘女’了,what?显然这个静态属性并没有进行序列化。其实,静态(static)成员变量是属于类级别的,而序列化是针对对象的~所以不能序列化哦。
  • 2)经过序列化和反序列化过程后,specialty字段变量值由'计算机专业'变为空了,为什么呢?其实是因为transient关键字,它可以阻止修饰的字段被序列化到文件中,在被反序列化后,transient 字段的值被设为初始值,比如int型的值会被设置为 0,对象型初始值会被设置为null。
serialVersionUID问题

serialVersionUID 表面意思就是序列化版本号ID,其实每一个实现Serializable接口的类,都有一个表示序列化版本标识符的静态变量,或者默认等于1L,或者等于对象的哈希码。

private static final long serialVersionUID = -6384871967268653799L;

serialVersionUID有什么用?

JAVA序列化的机制是通过判断类的serialVersionUID来验证版本是否一致的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID和本地相应实体类的serialVersionUID进行比较,如果相同,反序列化成功,如果不相同,就抛出InvalidClassException异常。

接下来,我们来验证一下吧,修改一下Student类,再反序列化操作

Exception in thread "main" java.io.InvalidClassException: com.example.demo.Student;
local class incompatible: stream classdesc serialVersionUID = 3096644667492403394,
local class serialVersionUID = 4429793331949928814
	at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:687)
	at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1876)
	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1745)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2033)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1567)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:427)
	at com.example.demo.Test.main(Test.java:20)

从日志堆栈异常信息可以看到,文件流中的class和当前类路径中的class不同了,它们的serialVersionUID不相同,所以反序列化抛出InvalidClassException异常。那么,如果确实需要修改Student类,又想反序列化成功,怎么办呢?可以手动指定serialVersionUID的值,一般可以设置为1L或者,或者让我们的编辑器IDE生成

private static final long serialVersionUID = -6564022808907262054L;

实际上,阿里开发手册,强制要求序列化类新增属性时,不能修改serialVersionUID字段~

如果某个序列化类的成员变量是对象类型,则该对象类型的类必须实现序列化

给Student类添加一个Teacher类型的成员变量,其中Teacher是没有实现序列化接口的

public class Student implements Serializable {
    
    private Integer age;
    private String name;
    private Teacher teacher;
    ...
}
//Teacher 没有实现
public class Teacher  {
......
}

序列化运行,就报NotSerializableException异常啦

Exception in thread "main" java.io.NotSerializableException: com.example.demo.Teacher
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
	at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
	at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
	at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
	at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
	at com.example.demo.Test.main(Test.java:16)

其实这个可以在上小节的底层源码分析找到答案,一个对象序列化过程,会循环调用它的Object类型字段,递归调用序列化的,也就是说,序列化Student类的时候,会对Teacher类进行序列化,但是对Teacher没有实现序列化接口,因此抛出NotSerializableException异常。所以如果某个实例化类的成员变量是对象类型,则该对象类型的类必须实现序列化

子类实现了Serializable,父类没有实现Serializable接口的话,父类不会被序列化。

子类Student实现了Serializable接口,父类User没有实现Serializable接口

//父类实现了Serializable接口
public class Student  extends User implements Serializable {

    private Integer age;
    private String name;
}
//父类没有实现Serializable接口
public class User {
    String userId;
}

Student student = new Student();
student.setAge(25);
student.setName("jayWei");
student.setUserId("1");

ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\text.out"));
objectOutputStream.writeObject(student);

objectOutputStream.flush();
objectOutputStream.close();

//反序列化结果
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\text.out"));
Student student1 = (Student) objectInputStream.readObject();
System.out.println(student1.getUserId());
//output
/** 
 * null
 */

从反序列化结果,可以发现,父类属性值丢失了。因此子类实现了Serializable接口,父类没有实现Serializable接口的话,父类不会被序列化。

八、序列化常见面试题

  • 序列化的底层是怎么实现的?
  • 序列化时,如何让某些成员不要序列化?
  • 在 Java 中,Serializable 和 Externalizable 有什么区别
  • serialVersionUID有什么用?
  • 是否可以自定义序列化过程, 或者是否可以覆盖 Java 中的默认序列化过程?
  • 在 Java 序列化期间,哪些变量未序列化?
1.序列化的底层是怎么实现的?

本文第六小节可以回答这个问题,如回答Serializable关键字作用,序列化标志啦,源码中,它的作用啦还有,可以回答writeObject几个核心方法,如直接写入基本类型,获取obj类型数据,循环递归写入,哈哈

2.序列化时,如何让某些成员不要序列化?

可以用transient关键字修饰,它可以阻止修饰的字段被序列化到文件中,在被反序列化后,transient 字段的值被设为初始值,比如int型的值会被设置为 0,对象型初始值会被设置为null。

3.在 Java 中,Serializable 和 Externalizable 有什么区别

Externalizable继承了Serializable,给我们提供 writeExternal() 和 readExternal() 方法, 让我们可以控制 Java的序列化机制, 不依赖于Java的默认序列化。正确实现 Externalizable 接口可以显著提高应用程序的性能。

4.serialVersionUID有什么用?

可以看回本文第七小节哈,JAVA序列化的机制是通过判断类的serialVersionUID来验证版本是否一致的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID和本地相应实体类的serialVersionUID进行比较,如果相同,反序列化成功,如果不相同,就抛出InvalidClassException异常。

5.是否可以自定义序列化过程, 或者是否可以覆盖 Java 中的默认序列化过程?

可以的。我们都知道,对于序列化一个对象需调用
ObjectOutputStream.writeObject(saveThisObject), 并用 ObjectInputStream.readObject() 读取对象, 但 Java 虚拟机为你提供的还有一件事, 是定义这两个方法。如果在类中定义这两种方法, 则 JVM 将调用这两种方法, 而不是应用默认序列化机制。同时,可以声明这些方法为私有方法,以避免被继承、重写或重载。

6.在 Java 序列化期间,哪些变量未序列化?

static静态变量和transient 修饰的字段是不会被序列化的。静态(static)成员变量是属于类级别的,而序列化是针对对象的。transient关键字修字段饰,可以阻止该字段被序列化到文件中。

Java序列化的几种方式 【Java序列化的几种方式】 阅读详情

相关推荐

别再只用真彩色了!手把手教你用ENVI主成分分析(PCA)给遥感图像‘美颜’与‘瘦身’

本文详细介绍了如何利用ENVI主成分分析(PCA)技术优化遥感图像处理,实现数据‘美颜’与‘瘦身’。通过PCA的维度压缩、噪声分离和特征增强三大优势,显著提升高光谱数据的可视化效果和分析效率。文章还提供了ENVI操作的最佳实践和常见问题解决方案,帮助读者掌握这一遥感图像处理的游戏规则改变者。

weixin_28465009的博客 277

详解JAVA序列化

进来,一文给你讲明白“序列化”。

BugMan的博客 9396

Vivado与Vscode无缝集成:高效Verilog开发环境搭建指南

本文详细介绍了如何将Vivado与Vscode无缝集成,打造高效的Verilog开发环境。通过替换Vivado默认编辑器为Vscode,配置必备插件和语法检查工具,开发者可以大幅提升FPGA项目的编码效率。文章还提供了代码片段、Testbench自动生成等高级技巧,帮助开发者快速上手这一集成方案。

weixin_33737774的博客 493

JAVA序列化

java序列化就是将java对象转换为二进制编码的过程。反序列化就是将二进制编码转换为java对象的过程。

jx的博客 1656

AvFrame和AvPacket

在FFmpeg中,未压缩的图像和压缩的视频码流分别使用AVFrame结构和AVPacket结构保存;针对视频编码器,其流程为从数据源获取图像格式的输入数据,保存为AVFrame对象并传入编码器,从编码器输出AVPacket结构。

Lce的专栏 3236

lvds接口_LVDS,接口,时序讲解,非常好的文章

欢迎FPGA工程师加入官方微信技术群点击蓝字关注我们FPGA之家-中国最好最大的FPGA纯工程师社群1.1.1 LVDS接口分类1.1.1.1 单路6bit LVDS这种接口电路中,采用单路方式传输,每个基色信号采用6位数据,共18位RGB数据,因此,也称18位或18bit LVDS接口。此,也称18位或18bit LVDS接口。1.1.1.2 双路6bit LVDS这种接口电...

weixin_39639286的博客 1905

Java基础:对象序列化详解

在我们平日开发中,经常让PO类去实现Serializable接口,然后让其可序列化。不过有时我们并不是特别清楚为什么要序列化,特别是对于纯Web项目开发的同学来说,需求环境不一定能用上。下面我简单和大家分享下自己对序列化的认知。......

weixin_39885962的博客 4339

STM32 之十三 看门狗(WDG)及低功耗下的处理

  最近在做低功耗项目时,遇到了看门狗不好处理的问题。在 ST 的各系列 MCU 中,看门狗应该算是使用配置起来最简单的一个外设了。我们通常仅需要配置很少的配置项,但是,一旦要配合低功耗模式则配置就比较麻烦了。MCU 中有两只狗,一只叫 Independent watchdog (IWDG);另一只叫 System window watchdog (WWDG)。下面是这两只狗的简单介绍! IWDG   IWDG 基本就等同于我们独立使用的看门狗芯片。最适合那些要求看门狗作为一个完全独立的进程在主应用程序之外

技术干货 7854

java序列化_全方位解析Java的序列化

前言相信大家日常开发中,经常看到Java对象“implements Serializable”。那么,它到底有什么用呢?本文从以下几个角度来解析序列这一块知识点~什么是Java序列化?为什么需要序列化?序列化用途Java序列化常用API序列化的使用序列化底层日常开发序列化的注意点序列化常见面试题一、什么是Java序列化?序列化:把Java对象转换为字节序列的过程反序列:把字节序列恢复为Java对象...

weixin_39520353的博客 696

MDIO接口协议与其详解——单片机

在单片机领域,通过MDIO接口可以与外部设备进行通信,实现对设备的控制和数据的读写。通过本文的介绍,你可以了解到MDIO接口协议的原理和使用方法,并参考源代码示例进行实际的开发和应用。具体的初始化方法与单片机的型号和开发环境有关,可以参考相应的单片机手册和开发工具的文档。(1)发送读取命令:向MDIO线发送读取命令,通常是发送一个特定的控制字节,用于指示要读取的寄存器地址。(1)发送写入命令:向MDIO线发送写入命令,通常是发送一个特定的控制字节,用于指示要写入的寄存器地址。二、MDIO接口协议使用方法。

web_class282的博客 2627

Vue2+OpenLayers动态绘制两个经纬度并计算距离(提供Gitee源码)

动态绘制两个经纬度并计算它们之间的距离。

黄团团的个人博客 366

Java程序员必备:序列化全方位解析

前言 相信大家日常开发中,经常看到Java对象“implements Serializable”。那么,它到底有什么用呢?本文从以下几个角度来解析序列这一块知识点~ 什么是Java序列化? 为什么需要序列化? 序列化用途 Java序列化常用API 序列化的使用 序列化底层 日常开发序列化的注意点 序列化常见面试题 一、什么是Java序列化? 序列化:把Java对象转换为字节序列的过程 反序列...

weiwenhou的博客 1331

基于STM32L4XX、HAL库的ESP32-S3-WROOM-1-N4 WIFI模块驱动程序设计

/ 检查是否收到完整的一行(以\r\n结尾)// 例如: 解析AT命令响应或MQTT消息等。// UART2初始化已在CubeMX中配置。// USART2初始化函数(由CubeMX生成)// 缓冲区溢出,重置。// 如果需要等待响应。// 处理接收到的数据。// 处理接收到的数据。// 等待ESP32模块启动。// 主循环其他任务。// 启用UART全局中断。// 发送HTTP GET请求。// 发送AT测试命令。// 连接Wi-Fi。// UART中断回调函数。

zhusl6688的博客 288

java序列化文件解析_Java程序员必备:序列化全方位解析

前言相信大家日常开发中,经常看到Java对象“implements Serializable”。那么,它到底有什么用呢?本文从以下几个角度来解析序列这一块知识点~什么是Java序列化?为什么需要序列化?序列化用途Java序列化常用API序列化的使用序列化底层日常开发序列化的注意点序列化常见面试题一、什么是Java序列化?序列化:把Java对象转换为字节序列的过程反序列:把字节序列恢复为Java对象...

weixin_39657521的博客 434

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

fegin调用为什么要序列化_全方位解析Java的序列化

前言相信大家日常开发中,经常看到Java对象“implements Serializable”。那么,它到底有什么用呢?本文从以下几个角度来解析序列这一块知识点~什么是Java序列化?为什么需要序列化?序列化用途Java序列化常用API序列化的使用序列化底层日常开发序列化的注意点序列化常见面试题一、什么是Java序列化?序列化:把Java对象转换为字节序列的过程反序列:把字节序列恢复为Java对象...

weixin_42542669的博客 667

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

session java 序列化_Java程序员必备:序列化全方位解析

原标题:Java程序员必备:序列化全方位解析前言 相信大家日常开发中,经常看到Java对象“implements Serializable”。那么,它到底有什么用呢?本文从以下几个角度来解析序列这一块知识点~什么是Java序列化?为什么需要序列化?序列化用途Java序列化常用API序列化的使用序列化底层日常开发序列化的注意点序列化常见面试题一、什么是Java序列化?序列化:把Java对象转换为字节...

weixin_42299125的博客 302

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Java程序员必备:序列化全方位最全解析

i++) { ...... //递归调用writeObject0()方法,写入对应的数据 writeObject0(objVals[i], fields[numPrimFields + i].isUnshared());i++) { if (slotDesc.hasWriteObjectMethod()) { //如果被序列化的对象自定义实现了writeObject()方法,则执行这个代码块 slotDesc.invokeWriteObject(obj, this);

java_xiaoo的博客 510

java 复制对象_Java程序员必备:序列化全方位解析

前言相信大家日常开发中,经常看到Java对象“implements Serializable”。那么,它到底有什么用呢?本文从以下几个角度来解析序列这一块知识点~什么是Java序列化?为什么需要序列化?序列化用途Java序列化常用API序列化的使用序列化底层日常开发序列化的注意点序列化常见面试题一、什么是Java序列化?序列化:把Java对象转换为字节序列的过程反序列:把字节序列恢复为Java对象...

weixin_39622521的博客 135

java复制对象_Java程序员必备:序列化全方位解析

前言相信大家日常开发中,经常看到Java对象“implements Serializable”。那么,它到底有什么用呢?本文从以下几个角度来解析序列这一块知识点~什么是Java序列化?为什么需要序列化?序列化用途Java序列化常用API序列化的使用序列化底层日常开发序列化的注意点序列化常见面试题一、什么是Java序列化?序列化:把Java对象转换为字节序列的过程反序列:把字节序列恢复为Java对象...

weixin_39869791的博客 79

java包

概图 分析: 一、最底层的是 JVM ///////////////////////////////////////////////////////////////////////////////////////////// 二、 base libraries java.lang、java.util、java.math 三个包 1. Math 解释了有关数学的知识,java.l...

htydowd的博客 307

Java第十四章小结

1.Java中流的分类有哪些? 流从流动方向上看:一般分为输入流和输出流 输入流:如System.in是一个InputStream类型输入流 输出流:如System.out 是一个PrintStream类型输出流 从读取类型上分:一般分为字节流和字符流 字节流:如System.in是一个InputStream类型字节流 字符流:如new InputStreamReader(System.in)是一个字符流对象 流从发生的源头:分为节点流和过滤流类 节点流:直接操作目标设备对应的流 。过滤流:继承带有关

weixin_52867343的博客 195

Java 语言程序设计(万字总结)

Java 语言的前身是Oak 语言 (1)语法简单,功能强大,安全可靠(2)与平台无关(3)解释编译两种运行方式(4)多线程(5)动态执行兼有丰富的API文档及类库 Java 应用程序(Java Application)、Java小应用程序(Java Applet)/Java小程序 程序是通过Java 解释器来执行的独立程序,可以使用命令行命令直接运行。整个程序的运行入口是main()方法,main()方法执行完毕,整个程序也即结束。 javac [选项] 源文件名java [选项] 程序名 [参数列表]J

weixin_42373488的博客 2418

如何抵御99.9%的攻击?金融Java系统1024安全配置全解析

掌握金融系统Java开发1024安全防护技巧,有效抵御99.9%网络攻击。涵盖HTTPS加密、权限控制、输入验证等核心配置,适用于高并发金融场景,提升系统稳定性与数据安全性。值得收藏的实战指南,点击了解完整方案。

Algorhythm的博客 788
上一篇: 保持清洁的Git提交记录,三招就够了
下一篇: 一文竟能读懂Docker架构原理
程序员职业指南
博客等级 码龄4年 2138粉丝 960原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值