- 浏览: 848218 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
贝塔ZQ:
读取excel文件,插件pageoffice也可以实现。
POI读写Excel文件(转)- - -
springmvc-freemarker:
java开源项目源码实例下载
java开源项目源代码 -
xuning2516:
第一种方法是个死循环啊。。。
Java NIO 拷贝文件(使用compact) -
u012046856:
...
SessionFactory.getCurrentSession与openSession的区别 -
Season_Wang:
赞一个呀,挺实用的
java swing 中的FileDialog
对象的序列化是非常有趣的,因为利用它可以实现“有限持久化”。请记住“持久化”意味着对象的“生存时间”并不取决于程序是否正在执行——它存在或“生存”于程序的每一次调用之间。通过序列化一个对象,将其写入磁盘,以后在程序重新调用时重新恢复那个对象,就能圆满实现一种“持久”效果。之所以称其为“有限”,是因为不能用某种“persistent”(持久)关键字简单地地定义一个对象,并让系统自动照看其他所有细节问题(尽管将来可能成为现实)。相反,必须在自己的程序中明确地序列化和组装对象。
为序列化一个对象,首先要创建某些OutputStream对象,然后将其封装到ObjectOutputStream对象内。此时,只需调用writeObject()即可完成对象的序列化,并将其发送给OutputStream。相反的过程是将一个InputStream封装到ObjectInputStream内,然后调用readObject()。
语言里增加了对象序列化的概念后,可提供对两种主要特性的支持。RMI和JavaBean。
10.9.2 序列化的控制
1.特殊的安全问题
2.某一个子对象完全不必序列化
此时,通过实现Externalizable接口,用它代替Serializable接口,便可控制序列化的具体过程。这个Externalizable接口扩展了Serializable,并增添了两个方法:writeExternal()和readExternal()。在序列化和重新装配的过程中,会自动调用这两个方法,以便我们执行一些特殊操作。
public class Blips { /** * @param args * @throws IOException * @throws IOException * @throws ClassNotFoundException * @throws FileNotFoundException * @throws ClassNotFoundException */ public static void main(String[] args) throws IOException, ClassNotFoundException { ObjectOutputStream objectOutputStream = new ObjectOutputStream( new FileOutputStream("c:/Blips.txt")); objectOutputStream.writeObject(new Blip1()); objectOutputStream.writeObject(new Blip2()); objectOutputStream.close(); System.out.println("1111111111111111111"); ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("c:/Blips.txt")); objectInputStream.readObject(); objectInputStream.readObject(); objectInputStream.close(); System.out.println("222222222222222222222"); } } class Blip1 implements Externalizable { public Blip1() { System.out.println("Blip1.Blip1()"); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { System.out.println("Blip1.readExternal()"); } @Override public void writeExternal(ObjectOutput out) throws IOException { System.out.println("Blip1.writeExternal()"); } } class Blip2 implements Externalizable { Blip2() { System.out.println("Blip2.Blip2()"); } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { System.out.println("Blip2.readExternal()"); } @Override public void writeExternal(ObjectOutput out) throws IOException { System.out.println("Blip2.writeExternal()"); } }
恢复b1后,会调用Blip1默认构建器。这与恢复一个Serializable(可序列化)对象不同。在后者的情况下,对象完全以它保存下来的二进制位为基础恢复,不存在构建器调用。而对一个Externalizable对象,所有普通的默认构建行为都会发生(包括在字段定义时的初始化),而且会调用readExternal()。必须注意这一事实——特别注意所有默认的构建行为都会进行——否则很难在自己的Externalizable对象中产生正确的行为。
以下代码演示了保持和恢复一个Externalizable的过程:
要有默认的public构造函数,实现特定接口。
但是Serilizable可以不用默认构造函数。
若从一个Externalizable对象继承,通常需要调用writeExternal()和readExternal()的基础类版本,以便正确地保存和恢复基础类组件。
所以为了让一切正常运作起来,千万不可仅在writeExternal()方法执行期间写入对象的重要数据(没有默认的行为可用来为一个Externalizable对象写入所有成员对象)的,而是必须在readExternal()方法中也恢复那些数据。初次操作时可能会有些不习惯,因为Externalizable对象的默认构建行为使其看起来似乎正在进行某种存储与恢复操作。但实情并非如此。
class Blip3 implements Externalizable { int i; String s; // No initialization public Blip3() { System.out.println("Blip3 Constructor"); // s, i not initialized } public Blip3(String x, int a) { System.out.println("Blip3(String x, int a)"); s = x; i = a; // s & i initialized only in non-default // constructor. } public String toString() { return s + i; } public void writeExternal(ObjectOutput out) throws IOException { System.out.println("Blip3.writeExternal"); // You must do this: out.writeObject(s); out.writeInt(i); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { System.out.println("Blip3.readExternal"); // You must do this: s = (String) in.readObject(); i = in.readInt(); } public static void main(String[] args) { System.out.println("Constructing objects:"); Blip3 b3 = new Blip3("A String ", 47); System.out.println(b3.toString()); try { ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream( "Blip3.out")); System.out.println("Saving object:"); o.writeObject(b3); o.close(); // Now get it back: ObjectInputStream in = new ObjectInputStream(new FileInputStream( "Blip3.out")); System.out.println("Recovering b3:"); b3 = (Blip3) in.readObject(); System.out.println(b3.toString()); } catch (Exception e) { e.printStackTrace(); } } }
控制序列化过程时,可能有一个特定的子对象不愿让Java的序列化机制自动保存与恢复。一般地,若那个子对象包含了不想序列化的敏感信息(如密码),就会面临这种情况。即使那种信息在对象中具有“private”(私有)属性,但一旦经序列化处理,人们就可以通过读取一个文件,或者拦截网络传输得到它。
由于Externalizable对象默认时不保存它的任何字段,所以transient关键字只能伴随Serializable使用。
2. Externalizable的替代方法
我们可以实现Serializable接口,并添加(注意是“添加”,而非“覆盖”或者“实现”)名为writeObject()和readObject()的方法。一旦对象被序列化或者重新装配,就会分别调用那两个方法。也就是说,只要提供了这两个方法,就会优先使用它们,而不考虑默认的序列化机制。
这些方法必须含有下列准确的签名:
我们传递给它的Serializable对象似乎会被检查是否实现了自己的writeObject()。若答案是肯定的是,便会跳过常规的序列化过程,并调用writeObject()。readObject()也会遇到同样的情况。
还存在另一个问题。在我们的writeObject()内部,可以调用defaultWriteObject(),从而决定采取默认的writeObject()行动。类似地,在readObject()内部,可以调用defaultReadObject()。
private void writeObject(ObjectOutputStream stream) throws IOException; private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException
public class SerialCtl implements Serializable { String a; transient String b; public SerialCtl(String aa, String bb) { a = "Not Transient: " + aa; b = "Transient: " + bb; } public String toString() { return a + "\n" + b; } private void writeObject(ObjectOutputStream stream) throws IOException { stream.defaultWriteObject(); stream.writeObject(b); } private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); b = (String) stream.readObject(); } public static void main(String[] args) { SerialCtl sc = new SerialCtl("Test1", "Test2"); System.out.println("Before:\n" + sc); ByteArrayOutputStream buf = new ByteArrayOutputStream(); try { ObjectOutputStream o = new ObjectOutputStream(buf); o.writeObject(sc); // Now get it back: ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream(buf.toByteArray())); SerialCtl sc2 = (SerialCtl) in.readObject(); System.out.println("After:\n" + sc2); } catch (Exception e) { e.printStackTrace(); } } }
3. 版本问题
有时候可能想改变一个可序列化的类的版本(比如原始类的对象可能保存在数据库中)。尽管这种做法得到了支持,但一般只应在非常特殊的情况下才用它。此外,它要求操作者对背后的原理有一个比较深的认识,而我们在这里还不想达到这种深度。JDK 1.1的HTML文档对这一主题进行了非常全面的论述(可从Sun公司下载,但可能也成了Java开发包联机文档的一部分)。
10.9.3 利用“持久性”
如果两个对象都有指向第三个对象的句柄,该如何对这两个对象序列化呢?如果从两个对象序列化后的状态恢复它们,第三个对象的句柄只会出现在一个对象身上吗?如果将这两个对象序列化成独立的文件,然后在代码的不同部分重新装配它们,又会得到什么结果呢?
同一个流中相同的对象在持久化时表现为一个对象,read时占据同一个内存位置。
不同流中相同对象在持久化时没有办法知道对方,read时占据不同的内存位置。
若想保存系统状态,最安全的做法是当作一种“微观”操作序列化。如果序列化了某些东西,再去做其他一些工作,再来序列化更多的东西,以此类推,那么最终将无法安全地保存系统状态。相反,应将构成系统状态的所有对象都置入单个集合内,并在一次操作里完成那个集合的写入。这样一来,同样只需一次方法调用,即可成功恢复之。
只需简单地序列化Class对象,就能实现static字段的保存。
尽管类Class是“可以序列化的”,但却不能按我们希望的工作。所以假如想序列化static值,必须亲自动手。
使用objectOutputStream.writeObject(Circle.class);直接持久化类是不能持久化static变量的。必须使用以下代码
Line.serializeStaticState(objectOutputStream)。
class Line extends Shape2 implements Serializable { private static int color = RED; public static void serializeStaticState(ObjectOutputStream os) throws IOException { os.writeInt(color); } public static void deserializeStaticState(ObjectInputStream os) throws IOException { color = os.readInt(); } }
发表评论
-
web开发的一些问题(java方向)
2008-09-08 19:42 14351.分页的解决方案,通用性,分页时参数丢失问题,如何解决? 2 ... -
java开源项目源代码
2008-08-14 23:02 20925java开源项目 源代码 http://www.codase. ... -
thinking in java notes
2008-08-10 20:33 1417public class IOStreamDemo { / ... -
thinking in java notes
2008-08-09 14:42 1125覆盖一个方法时,只能产生已在方法的基础类版本中定义的异常,或者 ... -
Java优化编程(第二版)
2008-08-03 22:25 2463Java优化编程(第二版) ... -
2.2 JVM中对象的生命周期
2008-08-03 22:22 12792.2 JVM中对象的生命周期 在JVM运行空间中,对象的整 ... -
自我参考:Java学习的30个目标
2008-08-03 21:47 1241自我参考:Java学习的30个目标时间:2007-02-10 ... -
解析Java类和对象的初始化过程
2008-08-03 21:46 1213解析Java类和对象的初始化过程本篇教程来源于 完全教程网 原 ... -
Thinking in java notes
2008-08-01 16:02 1351switch 接受char,enum,byte,int cha ... -
Thinking in java notes
2008-07-22 15:14 1190============chapter 1 Basic=== ... -
JavaBeans教程
2008-07-18 10:14 1165JavaBeans教程 作者:Unkown ... -
AWTEventMulticaster
2008-07-16 10:44 2049http://download.java.net/jdk/jd ... -
Developing Java Beans
2008-07-15 17:54 1094Chapter1 Java Bean architect ... -
Java Enumeration (枚举类型) (2) -- switch语句语法有一点点特别
2008-07-15 11:20 2501http://www.blogjava.net/JafeLee ...
相关推荐
2. **自定义序列化**:通过实现Externalizable接口,自定义序列化和反序列化逻辑,适合需要优化性能或有特殊需求的场景。 3. **序列化过滤**:使用`transient`关键字忽略不想序列化的字段,或使用`@serialData`注解...
`Externalizable`接口允许对象完全控制序列化过程,而仅实现`Serializable`接口的类则采用默认的序列化方式。对于那些不希望被序列化的类或字段,可以使用`transient`或`volatile`关键字标记,它们会被忽略在序列化...
2. **实现Externalizable接口**:这个接口继承自`Serializable`,提供了更高级别的控制,允许开发者自己编写序列化逻辑。 3. **序列化兼容性**:`serialVersionUID`的作用在于保证版本兼容性。开发者可以通过显式...
### Java对象序列化标准知识点详解 #### 一、系统架构概览 **1.1 概览** Java 对象序列化是一种将Java对象的状态转换成字节流的过程,以便于在网络上传输或存储到磁盘上。Java序列化标准定义了一套规则来描述如何...
通过实现`Serializable`或`Externalizable`接口,我们可以控制对象如何被序列化和反序列化,同时`transient`关键字提供了保护敏感数据的手段。理解和熟练运用这些概念对于Java开发者来说非常重要,特别是在处理持久...
如果类实现了`Externalizable`接口,那么必须手动实现`writeExternal()`和`readExternal()`方法,这两个方法负责控制对象的序列化和反序列化逻辑。这样,开发者可以精确地控制哪些字段被序列化,以及如何恢复这些...
在本例中,我们使用 Serializable 接口实现序列化和反序列化,以便在网络上传输 UserMessage 对象。 Java 序列化和反序列化的优点包括: * 实现对象的持久化存储 * 实现对象的网络传输 * 实现对象的克隆 * 实现...
Serializable有一个子接口Externalizable,实现Externalizable接口的类可以自行控制对象序列化荷反序列化过程。 一般来说,没有必要自己实现序列化接口,直接交给Java虚拟机是上策。 实现了序列化接口的类,如果...
- **实现`Externalizable`接口**:这种方式提供更细粒度的控制,允许开发者自定义序列化和反序列化的过程。需实现`writeExternal()`和`readExternal()`两个方法。 **1.3 transient关键字** 对于某些敏感或不需要...
`Externalizable`接口继承自`Serializable`,并且添加了`writeExternal()`和`readExternal()`方法,开发者可以通过重写这两个方法来控制序列化和反序列化的具体过程。 #### 七、总结 Java对象序列化是一项重要的...
使用 `Externalizable` 接口的主要优点在于可以更精确地控制序列化和反序列化过程,这对于需要自定义序列化逻辑的对象非常有用。 #### 六、序列化中的注意事项 - **`transient` 关键字**:使用 `transient` 可以...
在Java编程语言中,对象流(也称为序列化)是一个重要的概念,它允许我们将Java对象转换为字节流,以便可以存储在磁盘上、通过网络传输或保存在持久性存储中。序列化是Java平台的标准特性,由java.io.Serializable...
JDK提供了一套内置的序列化机制,包括`ObjectOutputStream`和`ObjectInputStream`,以支持`Serializable`和`Externalizable`接口的实现。 序列化的过程可能对性能有影响,尤其是在大量对象需要被序列化时。为了优化...
`Externalizable`接口是`Serializable`的子接口,提供了更高级别的控制,让开发者可以自定义序列化和反序列化的行为。 **二、序列化的方法** 1. **默认序列化**:如果一个类只实现了`Serializable`接口,那么Java...
虽然实现`Serializable`接口能够方便地进行序列化和反序列化,但需要注意的是,序列化会暴露对象的内部状态,可能引发安全问题。此外,如果一个类包含不希望被序列化的字段,可以通过添加`transient`关键字来标记...
在Java中,要实现序列化,对象所属的类必须实现`Serializable`或`Externalizable`接口。 - **`Serializable`接口**:此接口没有定义任何方法或字段,仅作为标记接口存在。实现这一接口的类会默认采用JVM提供的序列...
3. 实现`Externalizable`接口则更为灵活,需要手动实现`writeExternal(ObjectOutput out)`和`readExternal(ObjectInput in)`方法,这允许开发者完全控制对象的序列化和反序列化过程。 序列化和反序列化对于数据的...