关于Java的I / O类的问题

时间:2015-07-13 07:30:12

标签: java inheritance java-io

我正在阅读关于java中的网络(客户端/服务器)的本教程,我对我不理解的东西有疑问。

https://docs.oracle.com/javase/tutorial/networking/sockets/readingWriting.html

我经常看到这个

BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

BufferedReader inputStream = new BufferedReader(new FileReader("xanadu.txt"));
PrintWriter outputStream = new PrintWriter(new FileWriter("characteroutput.txt"));

我知道BufferReader的构造函数是

BufferedReader(Reader in)

1)我也知道,因为InputStreamReader是由Reader类继承的,所以你可以通过BufferedReader构造函数传递它。但我的问题是为什么我们需要InputStreamReader?是因为InputStreamReader可以保存输入流(根据它在API中的构造函数)

编辑:我犯了错误,请忽略此

<德尔> 2)现在为下一部分,inputStream&amp; outputStream(根据API)继承自Object类。如何将这两个类分别分配为BufferedReader和PrintWriter。这是因为它们都是由对象类继承的,还是它们的另一个原因?因为如果是这种情况,怎么会有人知道你可以分配什么作为类,好像所有东西都被Object类继承。

3)最后但并非最不重要的是,这里有关于BufferedReader和PrintWriter的另一个问题

BufferedReader inputStream = new BufferedReader(new FileReader("xanadu.txt"));
PrintWriter outputStream = new PrintWriter(new FileWriter("characteroutput.txt"));

为什么这两个类选择通过FileReader和FileWriter类的引用?

我想我想要了解更多关于选择这些特定类的原因的信息。

提前致谢!

2 个答案:

答案 0 :(得分:6)

1)要构建BufferedReader,您需要Reader参数。 System.in不是Reader。 Java IO难题的每个部分只做一件事:InputStreamReaderReader获取InputStream,然后BufferedReader缓冲Reader

2)他们不能,正是因为#1。首先,将InputStream包装在ReaderWriter包装中,然后您可以执行其他操作。

3)因为他们正在读取/写入文件,而不是流。 (编辑:并且,正如评论中提到的pvg一样,inputStream = new BufferedReader(...)outputStream = new PrintWriter(...)是非常令人困惑的变量名称。)

基本上,它就像一个制造商。您有System.in,这是InputStream。这意味着他正在交给你简单的字节。你不想要普通的字节;你希望被赋予字符(即由某些字符编码解析的字节,例如UTF-8)。但InputStream并不知道如何做到这一点。

输入InputStreamReader。每个Reader,他都知道如何给你角色。具体来说,InputStreamReader知道如何从InputStream获取字节并将其作为字符移交。所以你让他在System.in面前排成一行,所以你不必与他打交道。

但是你不想一次得到一个角色。你想要更多。您希望能够一次读取整行!你想......一个缓冲区!输入BufferedReader:他是站在另一个Reader面前的人,收集每个角色并仓鼠离开,直到你要求其中一些。

要准确了解发生了什么,您需要了解基于字节的IO和基于文本的IO之间的关键区别,并研究每个类&#39;构造函数,看看它包装的确切类型(虽然名称是一个很好的提示)。

答案 1 :(得分:0)

好的,这是一个简单的原因

这是装饰设计模式。 你拿一个基本的物体,并继续在它上面添加所需的装饰。 示例:带有2个配料的披萨(我现在很饿)

你这样做是因为它减少了所需的不同类的数量(InputStreamReader * Buffered / UnBuffered * bla bla bla导致许多不同的组合,所以如果我们每个组合有一个子类,它将是100多个流类,我们将被混淆,所以我们只是装饰它(所有类型都有相同的接口,我们在构造函数中相互传递)

如果仍然有疑问,只需谷歌装饰模式了解详情