Java基础教程——序列化

序列化

序列化:Serialize,将Java对象写入IO流(可以保存在数据库,文件等)
反序列化:Deserialize,从IO流中读取并恢复Java对象。

这么理解:序列化就是把对象封印起来,反序列化就是解封。

对象中包含的不仅仅是字符,更多的是非字符,因此需要使用字节流。

所有能在网上传输的对象的类都应该是可序列化的,否则程序就会出现异常。

实现Serializable接口

这个接口里面什么都没有,是一个标记接口,表明一个对象是可以序列化的。

public interface Serializable {
}

transient:瞬态关键字
|--transient变量---不参与序列化(有些变量可能属于敏感信息,如银行账户密码等)

transient:短暂的。

import java.io.*;
public class 序列化1 {
    public static void main(String[] args) throws Exception {
        int r_w = 3;
        if (r_w == 1) {
            on序列化();
        } else if (r_w == 2) {
            on反序列化();
        } else {
            on序列化();
            on反序列化();
        }
    }
    private static void on序列化() throws Exception {
        Dog _d = new Dog("狗", "金毛");
        File f = new File("myObj.txt");
        System.out.println("序列化:" + f.getAbsolutePath());
        FileOutputStream fos = new FileOutputStream(f);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(_d);
        oos.close();
        fos.close();
    }
    private static void on反序列化() throws Exception {
        // 前提:1.类必须可序列化,2.必须有对应的类文件
        File f = new File("myObj.txt");
        FileInputStream fis = new FileInputStream(f);
        ObjectInputStream ois = new ObjectInputStream(fis);
        Dog d = (Dog) ois.readObject();
        System.out.println("反序列化:" + d + ": name = " + d.name);
        ois.close();
        fis.close();
    }
}
class Dog implements Serializable {
    private static final long serialVersionUID = 1L;
    public Dog(String name, String type) {
        super();
        this.name = name;
        this.type = type;
    }
    String name;
    transient String type;
    @Override
    public String toString() {
        System.out.println("type:没参与序列化");
        return "【狗狗:name = " + name + ", type = " + type + "】";
    }
}

运行结果:

序列化:C:\Users\Administrator\git\Ah01JspJavaHtml\myObj.txt
type:没参与序列化
反序列化:【狗狗:name = 狗, type = null】: name = 狗

序列号: serialVersionUID
|--修改类的定义,可能生成新的序列号
|--|--改构造器:变
|--|--改字段:变(包括transient字段)
|--|--改方法体里的实现,不变;

序列化和反序列化时的序列号如果不同,会抛出异常java.io.InvalidClassException
可以显示声明一个固定的序列号。如:

private static final long serialVersionUID = 1L;

*另一种序列化方法:实现Externalizable接口

Externalizable接口可以替代Serializable接口。

需要手提供一个无参构造方法,否则在反序列化的时候会抛出异常

java.io.InvalidClassException: ……; no valid constructor

同时还需要定义两个方法(writeExternal()和readExternal())来控制要序列化的字段。

下列示例,只有Dog类的实现和上例不一样,其余代码可以一样。

package ah.externalizable;
import java.io.*;
public class 序列化2 {
    public static void main(String[] args) throws Exception {
        on序列化();
        on反序列化();
    }
    private static void on序列化() throws Exception {
        Dog _d = new Dog("狗", "金毛");
        File f = new File("myObj.txt");
        System.out.println(f.getAbsolutePath());
        FileOutputStream fos = new FileOutputStream(f);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(_d);
        oos.close();
        fos.close();
    }
    private static void on反序列化() throws Exception {
        File f = new File("myObj.txt");
        FileInputStream fis = new FileInputStream(f);
        ObjectInputStream ois = new ObjectInputStream(fis);
        Dog d = (Dog) ois.readObject();
        System.out.println(d + ": name = " + d.name);
        ois.close();
        fis.close();
    }
}
class Dog implements Externalizable {
    public Dog() {
        // 不写空构造,读不出来(可以写)
    }
    public Dog(String name, String type) {
        super();
        this.name = name;
        this.type = type;
    }
    String name;
    String type;
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        // 不写的Field就不序列化
        out.writeUTF(name);
        out.writeUTF(type);
    }
    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        // 读取顺序务必和写入顺序相同
        name = in.readUTF();
        type = in.readUTF();
    }
    @Override
    public String toString() {
        return "【狗狗:" + name + ", 是一只" + type + "】";
    }
}

原文地址:https://www.cnblogs.com/tigerlion/p/11179232.html

时间: 2024-08-02 04:33:47

Java基础教程——序列化的相关文章

Java基础教程(25)--I/O流

??I/O流表示输入源或输出目标.流可以表示许多不同类型的源和目标,例如磁盘文件.设备.其他程序等. ??流支持许多不同类型的数据,包括字节.原始数据类型.字符和对象等.有些流只传递数据; 有些流则可以操纵和转换数据. ??无论各种流的内部是如何工作的,所有流都提供相同的简单模型:流是一系列数据.程序使用输入流从源头获取数据,一次一项: ??程序使用输出流将数据写入目的地,一次一项: ??在本文中,我们会看到流可以处理各种各样的数据,无论是基本数据还是复杂对象.先来几张IO流的全家福: ??In

Java基础教程 - 组合

1. 什么是组合? 如果一个类的对象和另一个类满足"has-a"关系的话,我们就可以在一个类中,把另一个类的对象作为其对象成员. 什么是"has-a"关系,举个例子:现在有一个类LapTop.class,还有一个是Moniter.class.好显然,Laptop "has-a" Moniter,也就是说,他们是满足"has-a"关系的.这时候,我们就可以把Moniter作为Laptop的一个数据成员. class Laptop

Java基础教程:面向对象编程

Java基础教程:面向对象编程 Java语言概述 Java语言特点 1.Java为纯面向对象的语言,它能够直接反映现实生活中的对象.总之,Everything is object! 2.平台无关性.Java为解释型语言,编译器会把Java代码变成"""中间代码",然后在JVM上解释执行. 3.Java提供了很多内置的类库,这些类库简化了开发人员的程序设计工作,同时缩短了项目开发时间. 4.Java语言提供了对Web应用的支持. 5.Java语言提供了较好的安全性和健

Java基础教程:面向对象编程[2]

Java基础教程:面向对象编程[2] 三大特性 封装 封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部份包装.隐藏起来的方法.封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问. 使用封装我们可以对成员变量进行更精确的控制,同时隐藏信息,实现细节等. 方法: public class Person{ private String name; private int age; ? public int getAge(){ return age;

Java基础教程:JDBC编程

Java基础教程:JDBC编程 快速开始 什么是JDBC JDBC 指 Java 数据库连接,是一种标准Java应用编程接口( JAVA API),用来连接 Java 编程语言和广泛的数据库. JDBC API 库包含下面提到的每个任务,都是与数据库相关的常用用法. 制作到数据库的连接. 创建 SQL 或 MySQL 语句. 执行 SQL 或 MySQL 查询数据库. 查看和修改所产生的记录. 从根本上来说,JDBC 是一种规范,它提供了一套完整的接口,允许便携式访问到底层数据库,因此可以用 J

Java基础教程:HashTable与HashMap比较

Java基础教程:HashTable与HashMap比较 1.  关于HashMap的一些说法: a)  HashMap实际上是一个"链表散列"的数据结构,即数组和链表的结合体.HashMap的底层结构是一个数组,数组中的每一项是一条链表. b)  HashMap的实例有俩个参数影响其性能: "初始容量" 和 装填因子. c)  HashMap实现不同步,线程不安全.  HashTable线程安全 d)  HashMap中的key-value都是存储在Entry中的

Java基础教程:多线程基础(2)——线程间的通信

Java基础教程:多线程基础(2)--线程间的通信 使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时还会使程序员对各线程任务在处理的过程中进行有效的把控与监督. 线程间的通信 思维导图 等待中 等待/通知机制 不使用等待/通知机制 我们可以使用使用sleep()与 whle(true) 死循环来实现多个线程间的通信. 虽然两个线程实现了通信,但是线程B必须不断的通过while语句轮训机制来检测某一个条件,这样会浪费CPU资源. 如果轮询间隔较小,更浪费时间间隔.如果轮训

Java基础教程:枚举类型

Java基础教程:枚举类型 枚举类型 枚举是将一具有类似特性的值归纳在一起的方法.比如,我们可以将周一到周日设计为一个枚举类型.彩虹的七种颜色设计为一个枚举类型. 常量实现枚举 我们通过定义常量的方式来实现,如下: Public static class RainbowColor { // 红橙黄绿青蓝紫七种颜色的常量定义 public static final int RED = 0; public static final int ORANGE = 1; public static fina

Java基础教程:内部类

Java基础教程:内部类 内部类 内部类,是指在一个类的内部定义的类.就像下面这样: public class EnclosingClass {   . . .   public class NestedClass {   . . .     } } 内部类拥有访问外部类所有元素(包括private.static)的访问权.当某个外部类的对象创建了一个内部类对象时,此内部类对象必定会秘密地捕获一个指向那个外围类对象的引用.然后,在你访问此外围类的成员时,就是用那个引用来选择外围类的成员. 内部类