Java 如何初始化InputStream类型的System.in?
我知道,在java中,抽象类只能被引用,不能被初始化Java 如何初始化InputStream类型的System.in?,java,Java,我知道,在java中,抽象类只能被引用,不能被初始化InputStream是一个抽象类,在系统类中,我注意到以下声明 static InputStream in; 因此,如果我们希望代码System.in.read()工作,则需要初始化变量in 我的问题是java是如何做到这一点的?如果InputStream是抽象的,那么其他一些子类应该扩展它。默认情况下是哪个类?系统类中的声明如下: public final static InputStream in = null; 请看一下: “标准”
InputStream
是一个抽象类,在系统
类中,我注意到以下声明
static InputStream in;
因此,如果我们希望代码System.in.read()
工作,则需要初始化变量in
我的问题是java是如何做到这一点的?如果
InputStream
是抽象的,那么其他一些子类应该扩展它。默认情况下是哪个类?系统类中的声明如下:
public final static InputStream in = null;
请看一下:
“标准”输入流。此流已打开并准备就绪
提供输入数据。通常,该流对应于键盘输入
或主机环境或用户指定的其他输入源
这意味着当JVM启动时,System.in由Java运行时初始化。关于你的问题:
如果InputStream是抽象的,那么其他一些子类应该对其进行扩展。
默认情况下是哪个类
许多类扩展了
InputStream
类,如:,…系统类中的声明如下:
public final static InputStream in = null;
请看一下:
“标准”输入流。此流已打开并准备就绪
提供输入数据。通常,该流对应于键盘输入
或主机环境或用户指定的其他输入源
这意味着当JVM启动时,System.in由Java运行时初始化。关于你的问题:
如果InputStream是抽象的,那么其他一些子类应该对其进行扩展。
默认情况下是哪个类
许多类扩展了InputStream
类,如:,…幸运的是,检查对象的类型系统很容易。in
指:
System.out.println(System.in.getClass().getName());
印刷品(为我):
所以它是一个缓冲输入流
。它是什么?那么
Field field = FilterInputStream.class.getDeclaredField("in");
field.setAccessible(true);
System.out.println(field.get(System.in).getClass().getName());
印刷品(对我来说也是):
因此,System.in
是一个FileInputStream
包装在BufferedInputStream
中。这是有意义的,如果您认为大多数操作系统都以与文件相同的方式处理控制台。实际上,这个FileInputStream
从引用的“文件”中读取
通过搜索对FileDescriptor.in
的引用,我找到了初始化System.in的代码:在私有静态方法System.initializeSystemClass
中:
FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
setIn0(new BufferedInputStream(fdIn));
setOut0(newPrintStream(fdOut, props.getProperty("sun.stdout.encoding")));
setErr0(newPrintStream(fdErr, props.getProperty("sun.stderr.encoding")));
initializeSystemClass
可能由本机代码调用,因为似乎没有对它的引用。幸运的是,检查对象的类型系统很容易。in
指:
System.out.println(System.in.getClass().getName());
印刷品(为我):
所以它是一个缓冲输入流
。它是什么?那么
Field field = FilterInputStream.class.getDeclaredField("in");
field.setAccessible(true);
System.out.println(field.get(System.in).getClass().getName());
印刷品(对我来说也是):
因此,System.in
是一个FileInputStream
包装在BufferedInputStream
中。这是有意义的,如果您认为大多数操作系统都以与文件相同的方式处理控制台。实际上,这个FileInputStream
从引用的“文件”中读取
通过搜索对FileDescriptor.in
的引用,我找到了初始化System.in的代码:在私有静态方法System.initializeSystemClass
中:
FileInputStream fdIn = new FileInputStream(FileDescriptor.in);
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
setIn0(new BufferedInputStream(fdIn));
setOut0(newPrintStream(fdOut, props.getProperty("sun.stdout.encoding")));
setErr0(newPrintStream(fdErr, props.getProperty("sun.stderr.encoding")));
initializeSystemClass
可能由本机代码调用,因为似乎没有对它的引用。在JVM引导过程中,幕后会发生一些黑魔法,将中的初始化为正确的值
例如,在Java8中,它是由一个名为initializeSystemClass()
的私有方法完成的。javadoc评论说:
“初始化系统类。在线程初始化后调用。”
阅读这篇文章,了解血淋淋的细节。它们可能在不同的Java版本中有所不同。。。尽管它们在Java6和Java8之间似乎没有改变
注:
System.in、out、err
的实际设置是通过native
方法完成的。System.set{In,Out,Err}
方法也使用这些本机方法
在Java 6到Java 8中,
中的字段被初始化为一个BufferedInputStream
,它封装了一个FileInputStream
。有趣的是,输入流通常不是针对“文件”。。。在/a文件系统中的对象意义上
在JVM引导过程中,有一些黑魔法在幕后发生,将中的初始化为正确的值
例如,在Java8中,它是由一个名为initializeSystemClass()
的私有方法完成的。javadoc评论说:
“初始化系统类。在线程初始化后调用。”
阅读这篇文章,了解血淋淋的细节。它们可能在不同的Java版本中有所不同。。。尽管它们在Java6和Java8之间似乎没有改变
注:
System.in、out、err
的实际设置是通过native
方法完成的。System.set{In,Out,Err}
方法也使用这些本机方法
在Java 6到Java 8中,
中的字段被初始化为一个BufferedInputStream
,它封装了一个FileInputStream
。有趣的是,输入流通常不是针对“文件”。。。在/a文件系统中的对象意义上
它很可能位于一个您没有源代码的地方-在一个内部类(sun.package中的某个地方)或JVM本身中。它很可能位于一个您没有源代码的地方-在一个内部类(sun.package中的某个地方)或者在JVM内部。我感谢你。它在JvmtiExport::post_vm_start
中调用,在(热点)src/share/vm/runtime/thread.cpp中调用。我感谢你。它在JvmtiExport::post_vm_start
中调用