请问System.in中的in是哪个类的实例?谢谢

有看到说是InputStream,但它是个抽象类啊。到底是哪个类呢?谢谢!我知道in是System的一个字段,它不也是一个对象引用吗?... 有看到说是InputStream,但它是个抽象类啊。到底是哪个类呢?谢谢!
我知道in是System的一个字段,它不也是一个对象引用吗?
展开
 我来答
zhh5919
推荐于2016-05-05 · TA获得超过330个赞
知道小有建树答主
回答量:483
采纳率:100%
帮助的人:512万
展开全部
问题:
System.in.read()表示从键盘读入一个字符,但袜厅是疑问产生了,
在System类中是这样定义in的。
public final static InputStream in = nullInputStream();

nullInputStream是这样实现的:
private static InputStream nullInputStream() throws NullPointerException {
if (currentTimeMillis() > 0)
return null;
throw new NullPointerException();
}

他不是返回null,就是抛出迅好燃异常,如何初始化in呢?又如何去调用一个抽象方法read()呢?

解答:
有趣的问题.不过写java.io相关的应用其实不需要去关心这个问题的.
但我想还是解释一下我对这个out,in的初始化的理解好了
我也看了一下java.lang.System的源代码.
System类里有大量的native方法,是调用本地代码的,这些代码很可能是由虚拟机来调用的.
System类的开头有一段:
static {
registerNatives();
}
这段代码会在虚拟机启动的时候就执行,它在虚拟机里注册System需要使用的一些本地代码
比亩虚如:
private static native Properties initProperties(Properties props);
private static native void setOut0(PrintStream out);
在windows下的话,它就告诉虚拟机到哪个dll文件里去找相应的实现

>然而,我知道out是一个PrintStream的对象,但我查看了有关的原代码:public final static PrintStream out = nullPrintStream();
>public final static InputStream in = nullInputStream();
在nullInputStream()方法里有注释解释为什么会设置为空:

/**
* The following two methods exist because in, out, and err must be
* initialized to null. The compiler, however, cannot be permitted to
* inline access to them, since they are later set to more sensible values
* by initializeSystemClass().
*/
private static InputStream nullInputStream() throws NullPointerException {
if (currentTimeMillis() > 0)
return null;
throw new NullPointerException();
}
也就说in, out, and err 初始化为null,然后会在后来由initializeSystemClass()方法类初始化成有意义的值
/**
* Initialize the system class. Called after thread initialization.
*/
private static void initializeSystemClass() {
props = new Properties();
initProperties(props);
sun.misc.Version.init();
FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
setIn0(new BufferedInputStream(fdIn)); !!!
setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true)); !!!
setErr0(new PrintStream(new BufferedOutputStream(fdErr, 128), true)); !!!

// Enough of the world is now in place that we can risk
// initializing the logging configuration.
try {
java.util.logging.LogManager.getLogManager().readConfiguration();
} catch (Exception ex) {
// System.err.println("Can′t read logging configuration:");
// ex.printStackTrace();
}

// Load the zip library now in order to keep java.util.zip.ZipFile
// from trying to use itself to load this library later.
loadLibrary("zip");

// Subsystems that are invoked during initialization can invoke
// sun.misc.VM.isBooted() in order to avoid doing things that should
// wait until the application class loader has been set up.
sun.misc.VM.booted();
}
in,out,err就是在以上方法以下三条语句里初始化的.
setIn0(new BufferedInputStream(fdIn)); !!!
setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true)); !!!
setErr0(new PrintStream(new BufferedOutputStream(fdErr, 128), true)); !!!

private static native void setIn0(InputStream in);
~~~~~~~
这是个native函数,是前面registerNatives()的时候注册了的.这个函数应该是把实际连接到输入输出设备的句柄传给虚拟机并赋值给in,out,err

至于:
>InputStream是个抽象的类,怎么能使用char=(char)System.in.read()读入一个字符
我想你还没有明白什么是面向对象.
看看下面代码,我用OutputStream(也是抽象类,跟InputStream对应的输出类)以方便演示:
import java.io.IOException;
import java.io.OutputStream;
public class HelloWorld {

public OutputStream out=null;

public void setOutputStream(OutputStream out){
this.out=out;
}

public static void main(String[] args) throws IOException{
HelloWorld h=new HelloWorld();
PrintStream myOut=System.out;//System.out是一个PrintStream
h.setOutputStream(myOut);
h.out.write("hello,world".getBytes());//一般没人这么写的
}
}
以上代码执行后会输出hello,world
h.out是OutputStream,也是个抽象类,为什么能write(o)呢?
因为PrintStream是OutputStream的子类,所以能被"当作"OutputStream传给h.setOutputStream(myOut);
h.out.write执行的时候实际上是调用这个传进来的PrintStream实例的write方法
同样System.in和out肯定也是在initializeSystemClass()的时候被赋予了一个实际的可用的子类
要能体会到面向对象的好处,就要逐渐适应"对接口编程"的思想,相同接口的对象可以根据需要方便的替换.
比如,我刚才传了一个PrintStream,因此HelloWorld输出到了屏幕上. 我如果传给OutputStream的另一个子类FileOutputStream,就会输出到文件里

>还有为什么不是说字符流:writer和reader一般用于UniCode的读写吗?为什么键盘的输入用reader类呢?
不知道你在哪里看到说writer和reader一般用于UniCode的读写

>最近正在看java.io包,晕死!里面用到了很多包装器,这个包装那个,那个又包装这个的,简直要崩溃
看一下设计模式--Decorator(装饰)模式,你就明白了

参考资料: http://qs12quexxxx.blog.hexun.com/6317088_d.html

yf1226001
2007-10-31
知道答主
回答量:18
采纳率:0%
帮助的人:14.6万
展开全部
System.in.read()
一次只能输入一个字符并且要使用异常处理机制。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
百度网友fa6f888
2007-10-31 · TA获得超过1056个赞
知道小有建树答主
回答量:519
采纳率:0%
帮助的人:516万
展开全部
in
public static final InputStream in“标准”输入流。此流已打搜衫运开并准备提供输入数据。通常,世梁此塌老流对应于键盘输入或者由主机环境或用户指定的另一个输入源。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
匿名用户
2007-10-31
展开全部
in 是空尺System的敬高域
"Typically this stream corresponds to keyboard input or another input source specified by the host environment or user."亮亏尺
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(2)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式