序列化serializable,java中serializable是什么
序列化serializable,java中serializable是什么详细介绍
本文目录一览: 什么是java序列化?如何实现java序列化?Serializable接口的作用是什么?
【答案】:我们有时候将一个java对象变成字节流的形式传出去或者从一个字节流中恢复成一个java对象,例如,要将java对象存储到硬盘或者传送给网络上的其他计算机,这个过程我们可以自己写代码去把一个java对象变成某个格式的字节流再传输,但是,jre本身就提供了这种支持,我们可以调用OutputStream的writeObject方法来做,如果要让java 帮我们做,要被传输的对象必须实现serializable接口,这样,javac编译时就会进行特殊处理,编译的类才可以被writeObject方法操作,这就是所谓的序列化。需要被序列化的类必须实现Serializable接口,该接口是一个mini接口,其中没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的。
java序列化--java.io.Serializable接口解析
使用java以来 序列化随处可见 至于为什么要用序列化 序列化能解决什么问题 作为一个普通的码农 一般不怎么会去深入研究 由于最近在看mina和公司内部涉及到nio框架的一些源码 里面涉及到hession java这两种序列化 至于hession序列化为什么会诞生以及在apache项目中使用如此广泛 以及java本身序列化存在哪些缺陷 甚是不解 为了解答上面抛出来的疑惑 以及进一步了解java的序列化机制 这里开个小头 从java的序列化接口Serializable开始说起
jdk包里的Serializable接口的注释主要说明了以下几点
类通过实现Serializable接口来启用序列化 否则该类的任何状态将无法被序列化 同时也无法用于反序列化
若继承的父类没有实现Serializable接口 但是又想让子类可序列化 有三个注意事项
a) 子类实现Serializable接口
b) 子类必须有可访问的无参构造方法 用于保存和恢复父类的public或protected或同包下的package字段的状态 否则在序列化或反序列化时会抛出RuntimeException异常
c) 对于序列化后的子类 在进行反序列化时 理论上无法初始化父类中private(不可访问)对象变量的状态或值
在对可序列化类中的属性进行序列化时 如果遇到不可序列化的对象变量 此时会针对不可序列化的类抛出NotSerializableException异常
对于可序列化的非数组类 强烈建议显示声明static型 long型 final型serialVersionUID字段用于标识当前序列化类的版本号 否则在跨操作系统 跨编译器之间进行序列化和反序列化时容易出现InvalidClassException异常
对于可序列化类中的static transient对象变量 在序列化时无法保存其状态或值 static对象变量在反序列化时取得的值为当前jvm中对应类中对应static变量的值 而transient(瞬态)关键字则一般用于标识那些在序列化时不需要传递的状态变量
简单的测试代码
import java io FileInputStream import java io FileNotFoundException import java io FileOutputStream import java io IOException import java io ObjectInputStream import java io ObjectOutputStream import java io Serializable
/** * 序列化测试 * * @author sume * */ public class SerializableImpl implements Serializable {
private static final long serialVersionUID = L
static String staticVal = static transient String transientVal = transient String val = val
/** * main */ public static void main(String[] args) throws FileNotFoundException IOException ClassNotFoundException { // 序列化 SerializableImpl sila = new SerializableImpl() ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream( Serializable txt )) objectOutputStream writeObject(sila ) objectOutputStream close()
// 反序列化 SerializableImpl staticVal = static ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream( Serializable txt )) SerializableImpl sila = (SerializableImpl) objectInputStream readObject() objectInputStream close()
// 比较各个属性的值 System out println(sila staticVal) System out println(sila transientVal) System out println(sila val) } }输出结果 static null val 从输出结果可以看出
反序列化后类中static型变量staticVal的值为当前jvm中对应static变量的值 为 static 而不是序列化时的值 static
transient关键字标识的变量的状态并没有在序列化中被保存 因此反序列化后
transientVal变量的值为null
第三个为常见的对象状态在序列化和反序列化过程中的传递
lishixinzhi/Article/program/Java/hx/201311/26282
java序列化为什么要实现serializable
不一定要 根据需求
序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。序列化的实现:将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。
序列化:序列化是将对象转换为容易传输的格式的过程。例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象。在另一端,反序列化将从该流重新构造对象。
是对象永久化的一种机制。
确切的说应该是对象的序列化,一般程序在运行时,产生对象,这些对象随着程序的停止运行而消失,但如果我们想把某些对象(因为是对象,所以有各自不同的特性)保存下来,在程序终止运行后,这些对象仍然存在,可以在程序再次运行时读取这些对象的值,或者在其他程序中利用这些保存下来的对象。这种情况下就要用到对象的序列化。
只有序列化的对象才可以存储在存储设备上。为了对象的序列化而需要继承的接口也只是一个象征性的接口而已,也就是说继承这个接口说明这个对象可以被序列化了,没有其他的目的。之所以需要对象序列化,是因为有时候对象需要在网络上传输,传输的时候需要这种序列化处理,从服务器硬盘上把序列化的对象取出,然后通过网络传到客户端,再由客户端把序列化的对象读入内存,执行相应的处理。
对象序列化是java的一个特征,通过该特征可以将对象写作一组字节码,当在其他位置读到这些字节码时,可以依此创建一个新的对象,而且新对象的状态与原对象完全相同。为了实现对象序列化,要求必须能够访问类的私有变量,从而保证对象状态能够正确的得以保存和恢复。相应的,对象序列化API能够在对象重建时,将这些值还原给私有的数据成员。这是对java语言访问权限的挑战。通常用在服务器客户端的对象交换上面,另外就是在本机的存储。
对象序列化的最主要的用处就是在传递,和保存对象(object)的时候,保证对象的完整性和可传递性。譬如通过网络传输,或者把一个对象保存成一个文件的时候,要实现序列化接口
C#里serializable是什么意思?
序列化后的对象可以在网络之间进行传输!
序列化。将ojbect用字符的形式储存起来。
序列化
序列化是指存储和获取磁盘文件、内存或其他地方中的对象。在序列化时,所有的实例数据都保存到存储介质上,在取消序列化时,对象会被还原,且不能与其原实例区别开来。
只需给类添加Serializable属性,就可以实现序列化实例的成员。
并行化是序列化的逆过程,数据从存储介质中读取出来,并赋给类的实例变量。
[Serializable]
public class Person
{
public Person()
{
}
public int Age;
public int WeightInPounds;
}
下面来看一个小例子,首先要添加命名空间
using System.Runtime.Serialization.Formatters.Binary;
下面的代码将对象Person进行序列化并存储到一个文件中
Person me = new Person();
me.Age = 34;
me.WeightInPounds = 200;
Stream s = File.Open("Me.dat",FileMode.Create);
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(s,me);
s.Close();
如果需要对部分字段序列化部分不序列化时,我们可以按照如下设置实现
[Serializable]
public class Person
{
public Person()
{ }
public int Age;
[NonSerialized]
public int WeightInPounds;
}
关于Serializable,为什么实现Serializable就能够实现序列化
最重要的两个原因是:
1、将对象的状态保存在存储媒体中以便可以在以后重新创建出完全相同的副本;
2、按值将对象从一个应用程序域发送至另一个应用程序域。
实现serializable接口的作用是就是可以把对象存到字节流,然后可以恢复。所以你想如果你的对象没实现序列化怎么才能进行网络传输呢,要网络传输就得转为字节流,所以在分布式应用中,你就得实现序列化,如果你不需要分布式应用,那就没那个必要实现序列化。
java中serializable是什么
java Serializable,就是java提供的通用数据保存和读取的接口。
序列化类的所有子类本身都是可序列化的。这个序列化接口没有任何方法和域,仅用于标识序列化的语意。允许非序列化类的子类型序列化,子类型可以假定负责保存和恢复父类型的公有的、保护的和(如果可访问)包的域的状态。只要该类(扩展)有一个无参构造子,可初始化它的状态,那么子类型就可承担上述职责。在这种情况下申明一个可序列化的类是一个错误。此错误将在运行时被检测。就是可以把对象存到字节流,然后可以恢复
一个对象序列化的接口,一个类只有实现了Serializable接口,它的对象才是可序列化的。因此如果要序列化某些类的对象,这些类就必须实现Serializable接口。而实际上,Serializable是一个空接口,没有什么具体内容,它的目的只是简单的标识一个类的对象可以被序列化。
深入探索Java对象的序列化
深入探索Java对象的序列化对象序列化就是把对象写入到输出流中,用来存储或者传输。对象的反序列化就是从输入流中读取对象。要序列化的对象应该实现Serializable接口。Serializable接口是一个标识接口,没有抽象方法。Serializable有一个子接口Externalizable,实现Externalizable接口的类可以自行控制对象序列化荷反序列化过程。一般来说,没有必要自己实现序列化接口,直接交给Java虚拟机是上策。实现了序列化接口的类,如果其成员不需要序列化进去,则使用transient关键字进行修饰。下面给出个例子:import java.io.*;/*** Java对象的序列化测试* File: ObjectStreamTest.java* User: leizhimin* Date: 2008-3-12 20:41:43*/public class ObjectStreamTest {public static void main(String args[]) {testObjectSeri();testObjectInSeri();}/*** 对象序列化测试*/public static void testObjectSeri() {Person person = new Person("熔岩", "341022225562156", "lavasoft");FileOutputStream fos = null;ObjectOutputStream oos = null;try {fos = new FileOutputStream("Q:\study\java5study\src\io\person.dat");oos = new ObjectOutputStream(fos);oos.writeObject(person);} catch (FileNotFoundException e) {System.out.println("找不到指定的文件!");e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {oos.flush();oos.close();} catch (IOException e) {e.printStackTrace();}}}/*** 对象反序列化测试*/public static void testObjectInSeri() {FileInputStream fis = null;ObjectInputStream ois = null;Person person = null;try {fis = new FileInputStream("Q:\study\java5study\src\io\person.dat");ois = new ObjectInputStream(fis);person = (Person) ois.readObject();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();} finally {try {ois.close();} catch (IOException e) {e.printStackTrace();}}System.out.println(person.toString());}}/*** 测试序列化所用的类*/class Person implements Serializable {private String username;private String cardNumber;private transient String password;public Person(String username, String cardNumber, String password) {this.username = username;this.cardNumber = cardNumber;this.password = password;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getCardNumber() {return cardNumber;}public void setCardNumber(String cardNumber) {this.cardNumber = cardNumber;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String toString() {StringBuffer sb = new StringBuffer(this.getClass().getName());sb.append("[");sb.append(" ");sb.append("username=" + this.username);sb.append(" ");sb.append("cardNumber=" + this.cardNumber);sb.append(" ");sb.append("password=" + this.password);sb.append("]");return sb.toString();}}运行结果为:io.Person[username=熔岩cardNumber=341022225562156password=null]Process finished with exit code 0属性password=null,说明在序列化过程中忽略了。说到此,还有一个容易忽略的问题--serialVersionUID :序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。如果接收者加载的该对象的类的 serialVersionUID 与对应的发送者的类的版本号不同,则反序列化将会导致 InvalidClassException。可序列化类可以通过声明名为 "serialVersionUID" 的字段(该字段必须是静态 (static)、最终 (final) 的 long 型字段)显式声明其自己的 serialVersionUID:ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;如果可序列化类未显式声明 serialVersionUID,则序列化运行时将基于该类的各个方面计算该类的默认 serialVersionUID 值,如“Java(TM) 对象序列化规范”中所述。不过,强烈建议 所有可序列化类都显式声明 serialVersionUID 值,原因计算默认的 serialVersionUID 对类的详细信息具有较高的敏感性,根据编译器实现的不同可能千差万别,这样在反序列化过程中可能会导致意外的 InvalidClassException。因此,为保证 serialVersionUID 值跨不同 java 编译器实现的一致性,序列化类必须声明一个明确的 serialVersionUID 值。还强烈建议使用 private 修改器显示声明 serialVersionUID(如果可能),原因是这种声明仅应用于立即声明类 -- serialVersionUID 字段作为继承成员没有用处。serialVersionUID 在Eclipse里可以自动生成,可是在其他大部分IDE工具里面都不能自动生成。但是这个long型值取多少,心里没底,与其写还不如不写。
什么是序列化,在java中如何实现序列化?
一、什么是序列化:\x0d\x0a序列化理解成“打碎”是可以的,不过在书本上的名词就是将对象转换成二进制。\x0d\x0a\x0d\x0a二、在java中如何实现序列化:\x0d\x0a首先我们要把准备要序列化类,实现 Serializabel接口\x0d\x0a例如:我们要Person类里的name和age都序列化\x0d\x0aimport java.io.Serializable;\x0d\x0a\x0d\x0apublic class Person implements Serializable { //本类可以序列化\x0d\x0a private String name ;\x0d\x0a private int age ;\x0d\x0a \x0d\x0a public Person(String name,int age){\x0d\x0a this.name = name ;\x0d\x0a this.age = age ;\x0d\x0a }\x0d\x0a public String toString(){\x0d\x0a return "姓名:" + this.name + ",年龄" + this.age ;\x0d\x0a }\x0d\x0a}\x0d\x0a\x0d\x0a然后:我们将name和age序列化(也就是把这2个对象转为二进制,统族理解为“打碎”)\x0d\x0apackage org.lxh.SerDemo;\x0d\x0a\x0d\x0aimport java.io.File;\x0d\x0aimport java.io.FileOutputStream;\x0d\x0aimport java.io.ObjectOutputStream ;\x0d\x0a\x0d\x0apublic class ObjectOutputStreamDemo { //序列化\x0d\x0a\x0d\x0a public static void main(String[] args) throws Exception {\x0d\x0a//序列化后生成指定文件路径\x0d\x0a File file = new File("D:" + File.separator + "person.ser") ; ObjectOutputStream oos = null ;\x0d\x0a//装饰流(流)\x0d\x0a oos = new ObjectOutputStream(new FileOutputStream(file)) ; \x0d\x0a//实例化类\x0d\x0a Person per = new Person("张三",30) ; oos.writeObject(per) ;//把类对象序列化\x0d\x0a oos.close() ;\x0d\x0a }\x0d\x0a}
java里实现了Serializable接口,序列化是什么意思呢
序列化是为了实现对象的持久化,与网络中对象的传递,可别序列化的
类也就是可以被objctStream操作,它可将类转换成二进制码,保存在
指定的文本文件中,或是通过网络从服务器传递到客户端,当想要恢
复对象的时候只要通过相应的objectStream就可以将对象完全的复原
在内存中,这样就实现了对象的持久化操作。
如果你想详细了解这些,建议你好好看看Thinking
in
java相应
的章节
javaBean为什么要实现 序列化 Serializable接口
Java的"对象序列化"能将一个实现了Serializable接口的对象转换成一组byte,这样日后要用这个对象时候,你就能把这些byte数据恢复出来,并据此重新构建那个对象了。这一点甚至在跨网络的环境下也是如此,这就意味着序列化机制能自动补偿操作系统方面的差异。也就是说,可以在Windows机器上创键一个对象,序列化之后,再通过网络传到Unix机器上,然后在那里进行重建。你不用担心在不同的平台上数据是怎样表示的,byte顺序怎样,或者别的什么细节。
对象转为字节叫做序列化,可以把内存中的对象保存到文件或者数据库中
Java的"对象序列化"能让你将一个实现了Serializable接口的对象转换成一组byte,这样日后要用这个对象时候,你就能把这些byte数据恢复出来,并据此重新构建那个对象了。这一点甚至在跨网络的环境下也是如此,这就意味着序列化机制能自动补偿操作系统方面的差异。也就是说,你可以在Windows机器上创键一个对象,序列化之后,再通过网络传到Unix机器上,然后在那里进行重建。你不用担心在不同的平台上数据是怎样表示的,byte顺序怎样,或者别的什么细节。
对象序列化本身就非常有趣,因为它能让你实现"轻量级的persistence(lightweight persistence)"。所谓persistence是指,对象的生命周期不是由程序是否运行决定的;在程序的两次调用之间对象仍然还活着。通过"将做过序列化处理的对象写入磁盘,等到程序再次运行的时候再把它读出来",你可以达到persistence的效果。之所以说"轻量级",是因为你不能用像"persistent"这样的关键词来直接定义一个对象,然后让系统去处理所有细节(虽然将来有可能会这样)。相反,你必须明确地进行序列化(serialize)和解序列化(deserialize)。
之所以要在语言里加入对象序列化是因为要用它来实现两个重要的功能。Java的远程方法调用(Remote Method Invocation简称RMI)能让你像调用自己机器上的对象那样去调用其它机器上的对象。当你向远程对象传递消息的时候,就需通过对象序列化来传送参数和返回值了。
对JavaBean来说,对象序列化也是必不可少的。Bean的状态信息通常是在设计时配置的。这些状态信息必须保存起来,供程序启动的时候用;对象序列化就负责这个工作。
序列化一个对象还是比较简单的,只要让它实现Serializable接口就行了(这是一个"标记接口(tagging interface)",没有任何方法)。但是,当语言引入序列化概念之后,它的很多标准类库的类,包括primitive的wrapper类,所有的容器类,以及别的很多类,都会相应地发生改变。甚至连Class对象都会被序列化。
要想序列化对象,你必须先创建一个OutputStream,然后把它嵌进ObjectOutputStream。这时,你就能用writeObject( )方法把对象写入OutputStream了。读的时候,你得把InputStream嵌到ObjectInputStream里面,然后再调用readObject( )方法。不过这样读出来的,只是一个Object的reference,因此在用之前,还得先下传。
对象序列化最聪明的一点是,它不仅能保存对象的副本,而且还会跟着对象里面的reference,把它所引用的对象也保存起来,然后再继续跟踪那些对象的reference,以此类推。这种情形常被称为"单个对象所联结的'对象网'"。这个机制所涵盖的范围不仅包括对象的成员数据,而且还包含数组里面的reference。如果你要自己实现对象序列化的话,那么编写跟踪这些链接的程序将会是一件非常痛苦的任务。但是,Java的对象序列化就能精确无误地做到这一点,毫无疑问,它的遍历算法是做过优化的。
---------------------------------------------------------------------
实现java.io.Serializable 接口的类是可序列化的。没有实现此接口的类将不能使它们的任一状态被序列化或逆序列化。
序列化类的所有子类本身都是可序列化的。这个序列化接口没有任何方法和域,仅用于标识序列化的语意。允许非序列化类的子类型序列化,子类型可以假定负责保存和恢复父类型的公有的、保护的和(如果可访问)包的域的状态。只要该类(扩展)有一个无参构造子,可初始化它的状态,那么子类型就可承担上述职责。在这种情况下申明一个可序列化的类是一个错误。此错误将在运行时被检测。就是可以把对象存到字节流,然后可以恢复!
例如:Integer实现了Serializable,所以可以把一个Integer的对象用IO写到文件里,之后再可以从文件里读出,如你开始写入的时候那个对象的intValue() 是5的话,那读出来之后也是5。这一点体现了用序化类的作用,即用来传送类的对象。
当一个JavaBean在构造工具内被用户化,并与其它Bean建立连接之后,它的所有状态都应当可被保存,下一次被load进构造工具内或在运行时,就应当是上一次修改完的信息。为了能做到这一点,要把Bean的某些字段的信息保存下来,在定义Bean时要使它实现Java.io.Serializable接口。例如:
public class Button implements Java.io.Serializable {……}
实现了序列化接口的Bean中字段的信息将被自动保存。若不想保存某些字(这里的Bean中字段的信息将被自动保存是什么意思?这个自动保存是怎么实现的?)
段的信息则可在这些字段前冠以transient或static关键字,transient和static变量的信息是不可被保存的。通常,一个Bean所有公开出来的属性都应当是被保存的,也可有选择地保存内部状态。Bean开发者在修改软件时,可以添加字段,移走对其它类的引用,改变一个字段的private、protected或public状态,这些都不影响类的存储结构关系。然而,当从类中删除一个字段,改变一个变量在类体系中的位置,把某个字段改成transient/static,或原来是transient/static,现改为别的特性时,都将引起存储关系的变化。
所谓的Serializable,就是java提供的通用数据保存和读取的接口。至于从什么地方读出来和保存到哪里去都被隐藏在函数参数的背后了。这样子,任何类型只要实现了Serializable接口,就可以被保存到文件中,或者作为数据流通过网络发送到别的地方。也可以用管道来传输到系统的其他程序中。这样子极大的简化了类的设计。只要设计一个保存一个读取功能就能解决上面说得所有问题。