在System.out.println()中输出

首先感到遗憾的是,这是一个非常基本的问题,我宣传我仍然是一个代码猴。 我在接受采访时被要求阐明System.out.println(); 我解释了以下方式

//this class belongs to java.lang package class System{ public static PrintStream out; } //this class belongs to java.io package class PrintStream{ public void println.. } 

我已经解释过System.out是有效的,因为这是我们在java中访问静态变量的方式,而out是PrintStream的一个对象,因此我们可以访问它的方法,总之为

 System.out.pritnln(); 

他让我模拟一个类似的程序,我跟踪它并没有用,因为System.out返回null

我的问题是在java中实例化的对象在哪里? 如果我没错,它是预定义的对象吗? 应该是什么细致的解释。

从技术上讲,我们应该叫什么? 是PrintStream类型的变量还是应该将其称为PrintStream类型的对象?

在实例化类时,System.out初始化为null 。 这是由nullPrintStream()方法设置的, nullPrintStream()返回null

当JVM初始化时,它调用initializeSystemClass()方法。 此方法调用本native方法setOut0() ,该方法将out变量设置为适当的值。

这可能看起来很奇怪,但由于以下原因,这是必要的操作:

  • out不能静态设置为值,因为System需要是第一个加载的类之一(在PrintStream之前)。
  • out必须是final以便其值不能被用户直接覆盖。
  • 由于out不能静态设置,并且是最终的,我们必须使用native方法setOut0()覆盖语言的语义。

我希望这有助于你理解。

System.out是一个普通的静态属性,它是由JVM在JVM初始化期间通过initializeSystemClass()方法设置的。 您甚至可以通过简单地调用System.setOut(printOutStream);更改它(尽管不建议这样做System.setOut(printOutStream); ,其中printOutStream是您要用作标准输出的流。

这是一篇很好的文章,详细介绍了System.out.println()的工作原理。

的System.out.println() –

考虑到这一点,让我们打破这一点,从点运算符开始。 在Java中,点运算符只能用于调用方法和变量,因此我们知道’out’必须是方法或变量。 现在,我们如何分类’出’? 好吧,’out’不可能是一种方法,因为没有括号 – ‘(’) – ‘out’之后,这意味着out显然不是一个被调用的方法。 而且,’out’不接受任何参数,因为只有方法接受参数 – 你永远不会看到像“System.out(2,3).println”这样的东西。 这意味着’out’必须是变量。

‘out’是用’System’类名本身调用的,而不是一个类(一个对象)的实例,然后我们知道’out’必须是一个静态变量,因为只有静态变量可以调用类名本身。 所以现在我们知道’out’是一个属于System类的静态成员变量。

注意到’println()’显然是一种方法,我们可以进一步对System.out.println()中的’out’进行分类。 我们已经推断’out’是一个属于System类的静态变量。 但是现在我们可以看到’out’必须是一个类的实例,因为它正在调用方法’println()’。

上面有目的地说明了应该用来得出答案的思维过程。 如果事先不知道确切的答案,您可以通过应用Java的一些基本知识来达到近似的答案。 大多数采访者都不希望你知道System.out.println()是如何工作的,但更愿意看到你使用你的基本Java知识来得到一个接近精确的答案。

对原始问题更准确的答案是:在System类中是’out’的声明,如下所示:’public static final PrintStream out’,而在Prinstream类中是’println()’的声明方法签名,如下所示:’public void println()’。

以下是System.out.println()的不同部分:

 //the System class belongs to java.lang package class System { public static final PrintStream out; //... } //the Prinstream class belongs to java.io package class PrintStream{ public void println(); //... } 

System.out由JVM提供。 在调用main方法时,System.out已打开并可供使用。

请参阅http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#out

在Oracle Java运行时库中,它使用registerNatives()本机方法进行本机实例化,该方法在加载System类时被调用(通过static初始化程序)。 然而,这是一个实现细节。

您也可以使用System.setOut()直接设置System.out

System.out.pritln中的Out是System类中PrintWriter的静态字段(对象),println是PrintWriter的方法。

参考:系统: http : //docs.oracle.com/javase/6/docs/api/java/lang/System.html PrintWriter: http : //docs.oracle.com/javase/6/docs/api/java /io/PrintWriter.html

甚至没有必要去网络和文档。 我们可以简单地说javap java.lang.System这给出了所有静态字段的列表,属于System类的方法原型。 我们可以使用javap获取任何java类的详细信息,前提是您知道它的包和类名是System类中定义的PrintStream的公共静态对象。

当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是final,这意味着它不能在initializeSystemClass()中设置为其他东西,但是使用本机代码可以修改最终变量。

out是System类中定义的对象PrintStream类。 out被声明为public,static和final。

  • println()是PrintStream类的一种方法。
  • 使用out对象调用println()方法。
  • 使用System类调用out对象。

的System.out.println();

这里println是printstream类的对象。我们不能直接为printstream类创建对象。 Out是系统类的对象。 out在系统类中称为字段。 在调用system.out时,它间接为printstream类创建对象。 因此我们可以使用System.out.prontln()调用println()方法。