![](/img/trans.png)
[英]Why we can't call 'println()' method with help of PrintStream class where out is object of this class?
[英]PrintStream object out is initialized by null, how we call method on it?
我已經在System
類中看到out
對象(類型為PrintStream
)用null
值初始化。 我們如何調用類似System.out.prinln("");
? 在System類中,以這種方式初始化out變量:
package java.lang;
public final class System {
public final static PrintStream out = nullPrintStream();
private static PrintStream nullPrintStream() throws NullPointerException {
if (currentTimeMillis() > 0) {
return null;
}
throw new NullPointerException();
}
}
如上所示,代碼out
變量由null初始化,並且此變量是最終變量,因此無法進一步初始化,那么我們如何使用“ out”變量。
注釋中有解釋:
/**
* 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().
*/
initializeSystemClass()
使用本機方法將標准流初始化為非空值。 本機代碼可以重新初始化聲明為final的變量。
JVM調用private static void initializeSystemClass()
方法對其進行初始化。
參見這兩行代碼:
setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true));
setErr0(new PrintStream(new BufferedOutputStream(fdErr, 128), true));
這是兩種本機方法:
private static native void setOut0(PrintStream out);
private static native void setErr0(PrintStream err);
上面有一篇不錯的文章 。
有一個getter
和setter
的out
對象。
初始化System類時,它將調用其initializeSystemClass()
方法,下面是代碼:
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
setOut0(new PrintStream(new BufferedOutputStream(fdOut, 128), true));
在此代碼中,setOut0()是在System.c中實現的本機函數:
JNIEXPORT void JNICALL
Java_java_lang_System_setOut0(JNIEnv *env, jclass cla, jobject stream)
{
jfieldID fid =
(*env)->GetStaticFieldID(env,cla,"out","Ljava/io/PrintStream;");
if (fid == 0)
return;
(*env)->SetStaticObjectField(env,cla,fid,stream);
}
這是一個標准的JNI代碼,將System.out
設置為傳遞給它的參數,該方法調用本地方法setOut0()
,該方法將out變量設置為適當的值。
System.out是最終的,這意味着無法在initializeSystemClass()
中將其設置為其他值,但是使用本機代碼可以修改最終變量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.