您的位置:首页 > 大数据 > 物联网

Java 网络编程[Elliotte R.H.] 中对InputStream.markSupported()方法的误解

2015-11-02 16:45 537 查看
Elliotte 在书中(第四版35页,中译版42页)指出,
InputStream.markSupported()
方法的是一个设计上的失误,毕竟,
java.io
包中,“仅有两个类始终支持标记(
BufferedInputStream
ByteArrayInputStream
)”。

其实他的说法也没错,就当个类而言,这不得不说是一个非常差的设计。但是,他忽略了一点,Java的IO库使用了装饰器模式,各个IO类并非独立存在,大多数可以相互串接,以添加所需特性。

举个例子,下面的代码中,两次测试同一个变量,但结果却不尽相同。如若按照Elliotte所言,使用一个单独的接口而不是超类中的公有方法,通过
instanceof
或反射机制,我们虽然能够得知该对象的顶层类,但却无法真正得知其底层对象是否支持标记。

import java.io.*;

/**
* @author Jekton
*/
public class Tester {
public static void main(String[] args) throws FileNotFoundException {

InputStream in = new FileInputStream("E:\\myWorkspace\\in.txt");

InputStream decorated = new DataInputStream(in);
System.out.println("markSupported() = " + decorated.markSupported());

// inputStream that has an additional decorator
decorated = new DataInputStream(new BufferedInputStream(in));
System.out.println("markSupported() = " + decorated.markSupported());

System.out.println("decorated instanceof DataInputStream = " +
(decorated instanceof DataInputStream));
}
}


程序将打印:

markSupported() = false
markSupported() = true
decorated instanceof DataInputStream = true


这里,很明显,
DataInputStream
并不支持标记,如果使用一个独立的接口的话,我们根本无法得知中间还有个
BufferedInputStream
(这也是装饰器模式的优点之一)。更有甚者,此时的
decorated
变量根本就没有
markSupported()
方法。

Java中,输入流过滤器类都继承
FilterInputStream
(当然,这也包括上面提到的
BufferedInputStream
),
FilterInputStream
重写(override)了超类
InputStream
markSupported()
, 其直接调用底层输入流的
markSupported()
方法

// FilterInputStream
public boolean markSupported() {
return in.markSupported();
}


而在像
BufferedInputStream
这一类支持标记的类中,则直接返回l
true


// BufferedInputStream
public boolean markSupported() {
return true;
}


如此一来,不管变量的类型如何,只要“装饰器链”中存在一个支持标记的类,
markSupported()
都将返回
true




注:图片截取自[Core Java, Cay S.Horstman, Gary Cornell, 9th edition, volume 2]

后记,Elliotte 的《Java IO》一书,也同样存在此错误。笔者给他发过邮件,可惜他并没有回复。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: