Java SerializableExternalizable实现序列化反序列化-实例-statictransient修饰的变量不会被序列化
Posted 二十六画生的博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java SerializableExternalizable实现序列化反序列化-实例-statictransient修饰的变量不会被序列化相关的知识,希望对你有一定的参考价值。
在JAVA中,对象的序列化和反序列化被广泛的应用到RMI(远程方法调用)及网络传输中。
实现Serializable接口 和实现Externalizable接口实现序列化、反序列化的区别:
1 类实现Serializable接口不用实现方法;类实现Externalizable接口需要实现writeExternal,readExternal方法,不然反序列后的对象不含有属性值,都是默认的初始值
2 类实现Serializable接口时无参构造函数和带参构造函数可以同时写,也可以不同时写(只写一个或都不写均可);类实现Externalizable接口时如果写了带参构造函数,则必须要写无参构造函数,不然报错
3 如果不实现Serializable 则 报错Exception in thread "main" java.io.NotSerializableException: 类路径和类名
4 无static修饰是对象属性,只用transient修饰,不序列化,反序列化后是默认值
5 有static修饰是类属性,不序列化,反序列化后是最新值
6 有static、transient同时修饰时,仍然是当作类属性处理
transient变量不会贯穿对象的序列化和反序列化,生命周期仅存于调用者的内存中而不会写到磁盘里进行持久化。
---------------------------
首先介绍一下序列化Serializable
通常一个类实现序列化方式是实现序列化接口: class XXX implements Serializable
序列化的作用:把数据长久的保存在磁盘中,磁盘和内存是不同的,内存一般在程序运行时占用,数据保存周期短,随程序结束而结束,磁盘可以长久保存数据
transient关键字的作用,在已实现序列化的类中,有的变量不需要保存在磁盘中,就要transient关键字修饰,如银行卡密码等,就这个作用------在已序列化的类中使变量不序列化
---------------------------
1 实现Serializable接口
package com.company;
/**
* Title:
*
* @Author
* @CreateTime 2019/6/3 16:04
*/
import java.io.Serializable;
public class User1 implements Serializable
//public class User1
//报错Exception in thread "main" java.io.NotSerializableException: Serializable.User1
private String name;
private int 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;
@Override
public String toString()
return "User1" +
"name='" + name + '\\'' +
", age=" + age +
'';
package com.company;
/**
* Title:
*
* @Author
* @CreateTime 2019/6/3 16:05
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SerializableDemo1
public static void main(String[] args) throws Exception, IOException
//初始化对象
User1 user = new User1();
user.setName("lisi");
user.setAge(22);
System.out.println(user);
//序列化对象到文件中
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("template2"));
oos.writeObject(user);
oos.close();
//反序列化
File file = new File("template2");
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
User1 newUser = (User1) ois.readObject();
System.out.println(newUser);
输出:
User1name='lisi', age=22
User1name='lisi', age=22
如果类User1中只有一个构造函数(带两个参数),没有无参构造函数,依然能正常序列化和反序列化。
2.1实现Externalizable
package com.company;
/**
* Title:
*
* @Author
* @CreateTime 2019/6/3 16:04
*/
import java.io.*;
public class User1 implements Externalizable
private String name;
private int 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;
@Override
public String toString()
return "User1" +
"name='" + name + '\\'' +
", age=" + age +
'';
@Override
public void writeExternal(ObjectOutput out) throws IOException
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
用1中同样的main方法,输出如下:
User1name='lisi', age=22
User1name='null', age=0
需要自己实现方法中的细节!
Externalizable继承了Serializable,该接口中定义了两个抽象方法:writeExternal()与readExternal()。当使用Externalizable接口来进行序列化与反序列化的时候需要开发人员重写writeExternal()与readExternal()方法。
2.2 User1类的实现方法修改为如下:
@Override
public void writeExternal(ObjectOutput out) throws IOException
out.writeObject(name);
out.writeInt(age);
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
name = (String) in.readObject();
age = in.readInt();
输出:
User1name='lisi', age=22
User1name='lisi', age=22
如果类User1中只有一个构造函数(带两个参数),没有无参构造函数,依然能正常序列化,但是反序列化时报错。
3 static修饰的变量不会被序列化
package com.company;
import java.io.*;
public class Main implements Serializable
private static final long serialVersionUID = 1L;
public static int staticVar = 5;
public static void main(String[] args)
try
//初始时staticVar为5
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream("result.obj"));
out.writeObject(new Main());
out.close();
//序列化后修改为10
Main.staticVar = 10;
ObjectInputStream oin = new ObjectInputStream(new FileInputStream(
"result.obj"));
Main t = (Main) oin.readObject();
oin.close();
//再读取,通过t.staticVar打印新的值
System.out.println(t.staticVar);
catch (FileNotFoundException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
catch (ClassNotFoundException e)
e.printStackTrace();
//10
import java.io.*;
public class Main24 implements Serializable
private static final long serialVersionUID = 1L;
public static int staticVar = 5;//类属性,不序列化,反序列化后是最新值
public static void main(String[] args)
try
//初始时staticVar为5
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream("result.obj"));
out.writeObject(new Main24());
out.close();
//原对象序列化后修改为10
//Main24.staticVar = 10;//类属性,不序列化,反序列化后是最新值
ObjectInputStream oin = new ObjectInputStream(new FileInputStream(
"result.obj"));
Main24 t = (Main24) oin.readObject();
oin.close();
//再读取,通过t.staticVar打印新的值
System.out.println(t.staticVar);
catch (FileNotFoundException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
catch (ClassNotFoundException e)
e.printStackTrace();
//5
public class Main24 implements Serializable
private static final long serialVersionUID = 1L;
public static transient int staticVar = 5;//类属性,不序列化,反序列化后是最新值
public static void main(String[] args)
try
//初始时staticVar为5
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream("result.obj"));
out.writeObject(new Main24());
out.close();
//序列化后修改为10
//Main24.staticVar = 10;
ObjectInputStream oin = new ObjectInputStream(new FileInputStream(
"result.obj"));
Main24 t = (Main24) oin.readObject();
oin.close();
//再读取,通过t.staticVar打印新的值
System.out.println(t.staticVar);
catch (FileNotFoundException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
catch (ClassNotFoundException e)
e.printStackTrace();
//5
import java.io.*;
public class Main24 implements Serializable
private static final long serialVersionUID = 1L;
public transient int staticVar = 5;//对象属性,只用transient,不序列化,反序列化后是默认值值0
public static void main(String[] args)
try
//初始时staticVar为5
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream("result.obj"));
out.writeObject(new Main24());
out.close();
//序列化后修改为10
//Main24.staticVar = 10;
ObjectInputStream oin = new ObjectInputStream(new FileInputStream(
"result.obj"));
Main24 t = (Main24) oin.readObject();
oin.close();
//再读取,通过t.staticVar打印新的值
System.out.println(t.staticVar);
catch (FileNotFoundException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
catch (ClassNotFoundException e)
e.printStackTrace();
//0
序列化时,并不保存静态变量,这其实比较容易理解,序列化保存的是对象的状态,静态变量属于类的状态,因此 序列化并不保存静态变量。
Java序列化是不能序列化static变量的,因为其保存的是对象的状态,而static变量保存在全局数据区,在对象未实例化时就已经生成,属于类的状态。
这正是因为我们并没有序列化static变量,所以它并没有被写入流中,所以当我们要读取test的值时,它不可能在反序列化的文件里找到新的值,而是去全局数据区取值
参考:Java序列化与static_YXY_1989的博客-CSDN博客_static序列化
4 transient修饰的变量不会被序列化
Transient 关键字的作用是控制变量的序列化,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。
package com.company;
/**
* Title:
*
* @Author
* @CreateTime 2019/6/3 16:04
*/
import java.io.*;
public class User1 implements Serializable
private String name;
private int age;
private transient String t1;
private transient Integer t2;
private transient int t3;
public void setName(String name)
this.name = name;
public void setAge(int age)
this.age = age;
public void setT1(String t1)
this.t1 = t1;
public void setT2(Integer t2)
this.t2 = t2;
public void setT3(int t3)
this.t3 = t3;
@Override
public String toString()
return "User1" +
"name='" + name + '\\'' +
", age=" + age +
", t1='" + t1 + '\\'' +
", t2=" + t2 +
", t3=" + t3 +
'';
package com.company;
/**
* Title:
*
* @Author
* @CreateTime 2019/6/3 16:05
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SerializableDemo1
public static void main(String[] args) throws Exception, IOException
//初始化对象
User1 user = new User1();
user.setName("lisi");
user.setAge(22);
user.setT1("T1");
user.setT2(23);
user.setT3(24);
System.out.println(user);
//序列化对象到文件中
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("template1"));
oos.writeObject(user);
oos.close();
//反序列化
File file = new File("template1");
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
User1 newUser = (User1) ois.readObject();
System.out.println(newUser);
输出:
User1name='lisi', age=22, t1='T1', t2=23, t3=24
User1name='lisi', age=22, t1='null', t2=null, t3=0
参考:Java对象的序列化(Serialization)和反序列化详解_艾米莉Emily的博客-CSDN博客_对象序列化和反序列化
以上是关于Java SerializableExternalizable实现序列化反序列化-实例-statictransient修饰的变量不会被序列化的主要内容,如果未能解决你的问题,请参考以下文章