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

Elliotte 在书中(第四版35页,中译版42页)指出,InputStream.markSupported()方法的是一个设计上的失误,毕竟,java.io包中,“仅有两个类始终支持标记(BufferedInputStreamByteArrayInputStream)”。

其实他的说法也没错,就当个类而言,这不得不说是一个非常差的设计。但是,他忽略了一点,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)了超类 InputStreammarkSupported(), 其直接调用底层输入流的 markSupported()方法

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

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

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

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

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




后记,Elliotte 的《Java IO》一书,也同样存在此错误。笔者给他发过邮件,可惜他并没有回复。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值