- 浏览: 150417 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
accphc:
String是char[]的包装类,包装类的特质之一就是在对其 ...
Java中String类型的参数传递问题的解析 -
cyq7on:
lz,就最后没大懂,数组不是引用传递吗?
Java中String类型的参数传递问题的解析 -
di1984HIT:
xie de henhao a
Java class反编译后的代码还原 -
润之哥:
额 值传递 和引用传递 很蛋疼啦 ~~~
Java中String类型的参数传递问题的解析
在网上看了很多有关序列化的文章,我自己也写了两篇,现在感觉这些文章都没有很好的把序列化说清楚(包括我自己在内),所以在此我将总结前人以及自己的经验,用更浅显易懂的语言来描述该机制,当然,仍然会有不好的地方,希望你看后可以指出,作为一名程序员应该具有不断探索的精神和强烈的求知欲望!
序列化概述:
简单来说序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化,流的概念这里不用多说(就是I/O),我们可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间(注:要想将对象传输于网络必须进行流化)!在对对象流进行读写操作时会引发一些问题,而序列化机制正是用来解决这些问题的!
问题的引出:
如上所述,读写对象会有什么问题呢?比如:我要将对象写入一个磁盘文件而后再将其读出来会有什么问题吗?别急,其中一个最大的问题就是对象引用!举个例子来说:假如我有两个类,分别是A和B,B类中含有一个指向A类对象的引用,现在我们对两个类进行实例化{ A a = new A(); B b = new B(); },这时在内存中实际上分配了两个空间,一个存储对象a,一个存储对象b,接下来我们想将它们写入到磁盘的一个文件中去,就在写入文件时出现了问题!因为对象b包含对对象a的引用,所以系统会自动的将a的数据复制一份到b中,这样的话当我们从文件中恢复对象时(也就是重新加载到内存中)时,内存分配了三个空间,而对象a同时在内存中存在两份,想一想后果吧,如果我想修改对象a的数据的话,那不是还要搜索它的每一份拷贝来达到对象数据的一致性,这不是我们所希望的!
以下序列化机制的解决方案:
1.保存到磁盘的所有对象都获得一个序列号(1, 2, 3等等)
2.当要保存一个对象时,先检查该对象是否被保存了。
3.如果以前保存过,只需写入"与已经保存的具有序列号x的对象相同"的标记,否则,保存该对象
通过以上的步骤序列化机制解决了对象引用的问题!
序列化的实现:
将需要被序列化的类实现Serializable接口,该接口没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,使用ObjectOutputStream对象的writeObject(Object obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。
例子:
import java.io.*; public class Test { public static void main(String[] args) { Employee harry = new Employee("Harry Hacker", 50000); Manager manager1 = new Manager("Tony Tester", 80000); manager1.setSecretary(harry); Employee[] staff = new Employee[2]; staff[0] = harry; staff[1] = manager1; try { ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream("employee.dat")); out.writeObject(staff); out.close(); ObjectInputStream in = new ObjectInputStream( new FileInputStream("employee.dat")); Employee[] newStaff = (Employee[])in.readObject(); in.close(); /** *通过harry对象来加薪 *将在secretary上反映出来 */ newStaff[0].raiseSalary(10); for (int i = 0; i < newStaff.length; i++) System.out.println(newStaff[i]); } catch (Exception e) { e.printStackTrace(); } } } class Employee implements Serializable { public Employee(String n, double s) { name = n; salary = s; } /** *加薪水 */ public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; } public String toString() { return getClass().getName() + "[name = "+ name + ",salary = "+ salary + "]"; } private String name; private double salary; } class Manager extends Employee { public Manager(String n, double s) { super(n, s); secretary = null; } /** *设置秘书 */ public void setSecretary(Employee s) { secretary = s; } public String toString() { return super.toString() + "[secretary = "+ secretary + "]"; } //secretary代表秘书 private Employee secretary; }
修改默认的序列化机制:
在序列化的过程中,有些数据字段我们不想将其序列化,对于此类字段我们只需要在定义时给它加上transient关键字即可,对于transient字段序列化机制会跳过不会将其写入文件,当然也不可被恢复。但有时我们想将某一字段序列化,但它在SDK中的定义却是不可序列化的类型,这样的话我们也必须把他标注为transient,可是不能写入又怎么恢复呢?好在序列化机制为包含这种特殊问题的类提供了如下的方法定义:
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException; private void writeObject(ObjectOutputStream out) throws IOException;
(注:这些方法定义时必须是私有的,因为不需要你显示调用,序列化机制会自动调用的)
使用以上方法我们可以手动对那些你又想序列化又不可以被序列化的数据字段进行写出和读入操作。
下面是一个典型的例子,java.awt.geom包中的Point2D.Double类就是不可序列化的,因为该类没有实现Serializable接口,在我的例子中将把它当作LabeledPoint类中的一个数据字段,并演示如何将其序列化!
import java.io.*; import java.awt.geom.*; public class TransientTest { public static void main(String[] args) { LabeledPoint label = new LabeledPoint("Book", 5.00, 5.00); try { System.out.println(label);//写入前 ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("Label.txt")); out.writeObject(label); out.close(); System.out.println(label);//写入后 ObjectInputStream in = new ObjectInputStream(new FileInputStream("Label.txt")); LabeledPoint label1 = (LabeledPoint)in.readObject(); in.close(); System.out.println(label1);//读出并加1.0后 } catch (Exception e) { e.printStackTrace(); } } } class LabeledPoint implements Serializable { public LabeledPoint(String str, double x, double y) { label = str; point = new Point2D.Double(x, y); } private void writeObject(ObjectOutputStream out) throws IOException { /** *必须通过调用defaultWriteObject()方法来写入 *对象的描述以及那些可以被序列化的字段 */ out.defaultWriteObject(); out.writeDouble(point.getX()); out.writeDouble(point.getY()); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { /** *必须调用defaultReadObject()方法 */ in.defaultReadObject(); double x = in.readDouble() + 1.0; double y = in.readDouble() + 1.0; point = new Point2D.Double(x, y); } public String toString() { return getClass().getName() + "[label = "+ label + ", point.getX() = "+ point.getX() + ", point.getY() = "+ point.getY() + "]"; } private String label; transient private Point2D.Double point; }
发表评论
-
mina源码阅读1
2013-09-30 12:18 0服务端总体类结构如下:1. IoService接口: ... -
Address already in use:JVM_Bind 错误解决
2013-04-23 16:54 24552环境:win7 启动web工程的时候,报错: ... -
java回调函数的例子
2013-03-26 17:13 15877/** * * @author hongye.hw ... -
java 中annotation的使用
2013-03-10 18:32 4653最近在看一个同事写的web框架,其中大量使用了annotat ... -
jsoup使用
2013-01-14 11:09 969jsoup是一个开源的html解 ... -
jmock 中unexpected invocation错误
2012-02-29 14:58 4689远程服务接口 public interface Rem ... -
生产者消费者模式
2011-10-22 18:15 910import java.util.Random; im ... -
java timeTask
2011-10-09 11:28 1616项目中要使用时间程序,定时执行一段代码。google一下 ... -
Java class反编译后的代码还原
2011-02-17 14:15 7451Java class 利用jad 反编译之后,偶尔回碰 ... -
String作为参数传递
2010-10-06 21:48 2263import java.util.Arrays; ... -
继承与初始化
2010-09-30 17:27 883/** * @author hwy1782@gm ... -
线程池技术
2010-09-28 00:09 943转自:http://dev.csdn.net/ht ... -
堆排序
2010-09-23 10:24 960import org.junit.Test; /* ... -
数组的一个问题
2010-09-11 14:46 811一道基础题 int[] ... -
java中初始化顺序
2010-09-05 16:04 994假设有个Dog类 一个例子: ... -
堆和堆栈的区别
2010-09-05 15:32 1434堆和堆栈的区别 ... -
synchronized的用法(转)
2010-09-01 13:55 1001synchronized 关键字,它包括两种用法:sy ... -
java synchronized 用法
2010-09-01 13:51 858synchronized 的语法: sync ... -
关于String pool转自CSDN的一篇文章
2010-06-19 08:09 1112(原创)深入研究java对Stri ... -
String Pool
2010-06-18 22:29 1141在jvm中存在着String Pool String对象是 ...
相关推荐
Xson是一个Java对象序列化和反序列化程序。支持Java对象到字节数组的序列化,和从字节数组到Java对象的反序列化。 Maven: <groupId>com.github.xsonorg</groupId> <artifactId>xson-core <version>1.0.1 ...
java 对象的序列化与反序列化 java 对象的序列化与反序列化
java对象 java序列化 java反序列化
java 序列化对象 MARSHALLING UNMARSHALLING
序列化的过程就是对象写入字节流和从字节流中读取对象。将对象状态转换成字节流之后,可以用java.io包中的各种字节流类将其保存到文件中,管道到另一线程中或通过网络连接将对象数据发送到另一主机。对象序列化功能...
这是Java序列化标准规范,对于研究序列化源码能够提供指导作用,为深入研究Java序列技术奠定基础。
在java.beans包中,有两个好东西,XMLEncoder和XMLDecoder。从XML存取对象真是太费力气啦。做了小工具类,以后可以用用了。本文介绍了这两个可以把JAVA对象序列化保存为XML文件的工具类。
对象序列化.ppt 对象序列化.ppt 对象序列化.ppt 对象序列化.ppt 对象序列化.ppt
Java对象序列化详细解析.docJava对象序列化详细解析.docJava对象序列化详细解析.docJava对象序列化详细解析.docJava对象序列化详细解析.docJava对象序列化详细解析.docJava对象序列化详细解析.docJava对象序列化详细...
Java对象序列化的秘密
一个java 对象序列化的测试程序 . 。
java反序列化工具,覆盖jboss、weblogic、websphere。
本文介绍了Java对象序列化的五种方式,并提供了选择最适合应用程序的数据格式和技术所需要的全部信息。这篇文章侧重于可以用来生成 Java对象以数据为中心的视图的技术。演示可以把 JavaBeans变成XML文档的各种方法,...
NULL 博文链接:https://pxchen.iteye.com/blog/701552
极好的序列化与发序列化代码。可以处理array集合,数组或者单个对象等的序列化与反序列化。
将Java对象序列化成ISO-8859-1、Base64字节流和Xml字符串三种方式。
1.对象序列化的介绍 (1).NET支持对象序列化的几种方式 二进制序列化:对象序列化之后是二进制形式的,通过BinaryFormatter类来实现的,这个类位于System.Runtime.Serialization.Formatters.Binary命名空间下。 SOAP...
把Java对象转换为字节序列的过程称为对象的序列化。 把字节序列恢复为Java对象的过程称为对象的反序列化。 对象的序列化主要有两种用途: 1)把对象的字节序列地保存到硬盘上,通常存放在一个文件中...
Java中的序列化机制有两种实现方式: 一种是实现Serializable接口 另一种是实现Externalizable接口 区别: 实现Serializable接口 1 系统自动储存必要的信息 2 Java内建支持,易于实现,只需实现该接口即可,无须任何...
java基础 对象序列化