23.Java IO: Serializable && StreamTokenizer

来源:互联网 发布:宿州智慧云计算产业园 编辑:程序博客网 时间:2024/05/01 23:13

本文是在Java IO: SerializableStreamTokenizer和Java IO: StreamTokenizer 翻译而来。

Serializable

Java Serializiable 接口(java.io.Serializable)是一个标记接口,你的类必须实现它,如果他们需要序列化和反序列化。java对象序列化(写入)是通过ObjectOutStream完成,反序列化(读取)是通过ObjectInputStream完成。

Serializable是一个标记接口意味着它不包含任何方法。因此。类实现了Serializable不需要实现特定方法。实现Serializable因此只是告诉java序列化类目的是为对象序列化。

序列化例子

这里有一个例子类实现了java Serializable接口:

import java.io.Serializable;public static class Person implements Serializable {    public String name = null;    public int    age  =   0;}

和你看到的一样,Person类实现了序列化接口,但是实际上没有实现任何方法。像之前提到的一样,java Serializable接口只是一个标记接口,所以没有方法来实现。

查看完整的序列化和反序列化对象实现Serializable例子。查看教程ObjectInputStream 。

serialVersionUID

另外实现Serializable接口,类打算序列化也应该包含一个叫SerialVersinUID的private static final long变量。

下面是之前的Person类,加入了SerialVersinUID:

public static class Person implements Serializable {    private static final long serialVersionUID = 1234L;    public String name = null;    public int    age  =   0;}

serialVersionUID变量被Javad的对象序列化API用来决定一个反序列化对象被同一个版本的类序列化,像现在这样试图反序列化。

试想Person对象被序列化到硬盘。然后Person类发生了改变。然后你试着反序列化已排序的Person对象。现在已序列化的Person对象可能和新版本的Person类不相符。

为了检测这样的问题,类实现了Serializable应该包含一个SerialVersionUID变量。如果你对类做了大改变,你也应该改变它的SerialVersionUID值。

Java SDK和许多Java IDEs包含工具,这些工具可以用来产生SerialVersionUID,所以不需要你产生值。

今天的对象序列化

在当今的世界(2015和以后)许多Java项目序列话Java对象用不同的机制,比Java序列化机制多。例如,Java对象被序列话到JSON,BSON或其他更多优化的二进制格式。对象的优势也可被non-java应用读取。比如,运行在web浏览器的JavaScript可以本地序列话和反序列化对象到JSON和从JSON去序列化、反序列化对象。

其他的对象序列化机制通常不需要你的java类顺便实现Serializable。它们通常用Java 反射来查阅你的类,所以实现Serializable接口将是多余的-将增加没用的信息。
我有一个额外的教程,它关于序列化和反序列化Java对象到JSON 和从JSON中序列化和反序列化对象:Java JSON Tutorial . 。

更多关于序列化的信息

对象序列化本身是一种主题。Java IO教程多数聚焦在流和读写器上。因此,我不会深入关于对象序列化的详情。另外,网上已经有许多关于Java对象序列化的文章。为了不重复这些,我将给个这个主题深入的信息[链接](http://www.oracle.com/technetwork/articles/java/javaserial-1536170.html
).

Java IO: StreamTokenizer

Java StreamTokenizer类(java.io.StreamTokenizer)可以将从Reader中读取的字符分解为标记。例如,在字符串”Mary had a little lamb“中,每一个单词是一个对立的标记。

当你解析文件或计算机语言时,在进一步处理他们前,将输入分解为标记是很正常的。这个处理也称为”分析”或”分词“。

使用Java StreamTokenizer你可以在底层的Reader里通过标记移动。在一个线程里,你可以通过调用StreamTokenizer的nextToken()方法这样做。在每个nextToken()调用, StreamTOkenizer有几个变量,你可读取来查看已读取的变量是什么类型。查看它的值等等。这些变量是:

ttype : 读取的token类型(词,号码,行结束)
sval : 标记的字符值,如果标记是字符串(词)
nval : 标记的号码,如果标记是号码

StreamTokenizer例子

例如”

StreamTokenizer streamTokenizer = new StreamTokenizer(        new StringReader("Mary had 1 little lamb..."));while(streamTokenizer.nextToken() != StreamTokenizer.TT_EOF){    if(streamTokenizer.ttype == StreamTokenizer.TT_WORD) {        System.out.println(streamTokenizer.sval);    } else if(streamTokenizer.ttype == StreamTokenizer.TT_NUMBER) {        System.out.println(streamTokenizer.nval);    } else if(streamTokenizer.ttype == StreamTokenizer.TT_EOL) {        System.out.println();    }}streamTokenizer.close();

Java StreamTokenizer 是可以识别识别码,号码,引用字符串和各种评论风格。你也可以指定字符解释为空格,评论开始等等。在你开始解析评论前,所有这些事都已在StereamTOkenizer上被配置。查看JavaDoc获取更多关于它的信息。

关闭StreamTokenizer

当你完成从StreamTokenizer里读取标记,你该记得关闭它。关闭StreamTokenizer的同时也关闭了StreamTokenizer正在读取数据的Reader实例。

通过调用它的close()方法可以关闭StreamTokenizer。例如:

streamTokenizer.close();

你也在java7下用try-with-resources构造块。例如:

Reader reader = new FileReader("data/data.bin");try(StreamTokenizer streamTokenizer =    new StreamTokenizer(reader)){    while(streamTokenizer.nextToken() != StreamTokenizer.TT_EOF){        if(streamTokenizer.ttype == StreamTokenizer.TT_WORD) {            System.out.println(streamTokenizer.sval);        } else if(streamTokenizer.ttype == StreamTokenizer.TT_NUMBER) {            System.out.println(streamTokenizer.nval);        } else if(streamTokenizer.ttype == StreamTokenizer.TT_EOL) {            System.out.println();        }    }}

注意不再有任何直接的close()方法调用。try-with-resources构造块包含这些。

注意FileReader实例也没在try-with-resources块里创建。这意味着try-with-resources块不会自动关闭这个FileReader实例。然而,当StreamTokenizer关闭了,它也将关闭它读取的Reader,所以当StreamTokenizer关闭后,这个FileReader实例也将关闭。

1 0