我觉得应该看下定义吧 public static final InputStream in“标准”输入流。 此流已打开并准备提供输入数据。通常,此流对应于键盘输入或者由主机环境或用户指定的另一个输入源。System.in是 InputStream 的实例,而不是继承InputStream的类,为什么要重新定义呢?怎么重新定义啊?
我觉得应该看下定义吧 public static final InputStream in“标准”输入流。 此流已打开并准备提供输入数据。通常,此流对应于键盘输入或者由主机环境或用户指定的另一个输入源。System.in是 InputStream 的实例,而不是继承InputStream的类,为什么要重新定义呢?怎么重新定义啊?
很多人知道System.out是什么 却有的人不知道System.in是什么
public final static InputStream in = nullInputStream(); 这是in的定义. 然后去看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 初始化为null了. 然后实际运行时是通过initializeSystemClass()来初始化的. 再看 private static void initializeSystemClass() { 的代码,里面有 setIn0(new BufferedInputStream(fdIn)); 这个setIn0就是让 in = new BufferedInputStream(fdIn); 不过这是有c语言来实现的,因为in是final的,你不能通过java来改变它.到这就应该清楚了,in变量实际指向了 BufferedInputStream类型的对象.具体的read方法就去 BufferedInputStream的代码里找吧.
http://zhidao.baidu.com/question/38660871.html 建议看下,应该就会明白了,谢谢楼主的问题哦 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
建议多理解下JAVA I/O的“Decorator”模式
public static final InputStream in“标准”输入流。
此流已打开并准备提供输入数据。通常,此流对应于键盘输入或者由主机环境或用户指定的另一个输入源。System.in是 InputStream 的实例,而不是继承InputStream的类,为什么要重新定义呢?怎么重新定义啊?
public static final InputStream in“标准”输入流。
此流已打开并准备提供输入数据。通常,此流对应于键盘输入或者由主机环境或用户指定的另一个输入源。System.in是 InputStream 的实例,而不是继承InputStream的类,为什么要重新定义呢?怎么重新定义啊?
却有的人不知道System.in是什么
这是in的定义.
然后去看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 初始化为null了.
然后实际运行时是通过initializeSystemClass()来初始化的.
再看
private static void initializeSystemClass() {
的代码,里面有
setIn0(new BufferedInputStream(fdIn));
这个setIn0就是让
in = new BufferedInputStream(fdIn);
不过这是有c语言来实现的,因为in是final的,你不能通过java来改变它.到这就应该清楚了,in变量实际指向了 BufferedInputStream类型的对象.具体的read方法就去 BufferedInputStream的代码里找吧.
建议看下,应该就会明白了,谢谢楼主的问题哦
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
BufferedInputStream继承FilterInputStream,FilterInputStream继承InputStream
err “标准”错误输出流。
in “标准”输入流
out “标准”输出流。
去理解一下这个东西!!