我正在阅读关于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类的引用?
我想我想要了解更多关于选择这些特定类的原因的信息。
提前致谢!
答案 0 :(得分:6)
1)要构建BufferedReader
,您需要Reader
参数。 System.in
不是Reader
。 Java IO难题的每个部分只做一件事:InputStreamReader
从Reader
获取InputStream
,然后BufferedReader
缓冲Reader
。
2)他们不能,正是因为#1。首先,将InputStream
包装在Reader
或Writer
包装中,然后您可以执行其他操作。
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多个流类,我们将被混淆,所以我们只是装饰它(所有类型都有相同的接口,我们在构造函数中相互传递)
如果仍然有疑问,只需谷歌装饰模式了解详情