【问题标题】:What is System.out exactly?System.out 到底是什么?
【发布时间】:2015-11-24 02:31:09
【问题描述】:

我注意到,从尚未由命令行启动的 JAR 文件(即用户通过双击启动的 Runnable JAR 文件)对 System.out.println() 的任何调用都不会打开控制台。

在做了一些研究后,我在网站上找到了多个答案:

据我了解,System.out 不代表控制台。它确实代表了可以被任何需要显示它的东西处理的数据。 我说的对吗?

  • System.out 到底是什么?
  • 如何从用户双击启动的 Runnable JAR 文件打开控制台?

【问题讨论】:

    标签: java jar console executable-jar system.out


    【解决方案1】:

    现代操作系统(以及几个旧操作系统)中的进程获得三个与之相关的标准“流”:

    • 标准输入:基于流的输入 (stdin)
    • 标准输出:基于流的输出 (stdout)
    • 标准错误:基于流的错误输出 (stderr)

    集体(和创造性地)他们被称为standard streams。

    System.in、System.out 和 System.err 默认情况下是 Java 写入这些流的标准机制。

    从命令行调用的程序在命令行中的击键转到stdin 的环境中运行,stdout 和stderr 的输出在控制台中显示为文本。它们可以被重定向到文件等。

    通过 GUI 启动的程序通常不会将这些流与您可以看到的任何内容挂钩。

    我在上面说“默认情况下”,因为您可以使用对System 的调用来更改这些流指向的位置(它们具有诸如setIn、setOut 和setErr 之类的创意名称。)

    如何从用户双击启动的 Runnable JAR 文件打开控制台?

    那里存在错误的相关性:jar 可运行这一事实并不是您看不到流的原因。如果你在命令行运行一个可运行的 jar,你会看到它的标准输出。

    如果您在不与某种控制台关联的情况下运行该输出,是否可以看到该输出,这取决于您如何运行它,并且可能还取决于它是如何编写的。许多 GUI 框架会将标准输出重定向到日志文件。或者应用程序可能会提供这样做的调试选项。那里没有一个标准答案(没有双关语)。

    【讨论】:

    • 从命令行调用的程序是否具有重定向流,因为控制台本身是一个应用程序,它启动那些使用普通 Java 进程 API 的应用程序,就像任何其他程序一样?
    • @FrancescoMenzani:从命令行调用的程序通常没有有重定向流。假设你做java -r runnable.jar:操作系统运行java 程序,为其提供标准流。 java 程序加载 jar 并在新加载的 JVM 中为 System 设置流,以便从操作系统获取的流中读取和输出。
    • 如果他们没有重定向流,那么控制台如何处理他们的 IO?
    • @FrancescoMenzani:从这个意义上说,我不会使用“重定向”。控制台的流提供给它启动的子进程(这是任何时候进程启动子进程时的标准操作系统行为)。然后java 工具使它们可用于它正在运行的代码。对我来说,这不是重定向,但它可能是一个语义点。 (顺便说一句,感谢您的编辑;我总是拼错了 corre...corro...嗯...那个词。)
    【解决方案2】:

    这里,System.out 代表输出流 - 您的输出将流向何处。默认情况下,它设置为控制台。但是您可以将其更改为其他类似的文本文件。大多数情况下,在大型应用程序中它用于日志记录(通常由新程序员,坏主意)。在这种情况下,您可以在相应的日志文件中看到输出。

    【讨论】:

      【解决方案3】:

      System 是来自java.lang 包(java 中的默认包)的final 类,无法实例化。

      out 是System 类的static 成员字段,类型为PrintStream,其访问说明符为public final。

      println – 是PrintStream 类的重载方法。 println 打印传递给标准控制台的参数和换行符。有多个 println 具有不同参数的重载方法。每个println 都会调用 print 方法并添加一个换行符。在内部,打印调用 write() 和 write() 负责将数据显示到标准输出窗口。

      这是它的内部外观:

      //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 对象来将消息打印到屏幕上;我们只需在 System 类的 public static PrintStream 成员 out 上调用 println 方法。

      但是您不能创建PrintStream 的对象并调用println 函数。当您想打印到标准输出时,您将使用System.out。 这是唯一的方法。实例化 PrintStream 将允许您写入指定的 File 或 OutputStream,但与控制台没有任何关系。

      但是,您可以将System.out 传递给PrintStream,然后在PrintStream 对象上调用println 以打印到标准输出。这是一个小例子:

      import java.io.*;
      public class SystemOutPrintlnDemo
      {
        public static void main(String[] args) 
        {
          //creating PrintStream object
          PrintStream ps = new PrintStream(System.out);
          ps.println("Hello World!");
          ps.print("Hello World Again!");
          //Flushes the stream
          ps.flush();
        }
      }
      

      【讨论】:

      • 虽然可能是正确的,但我的问题与语法无关。我想知道班级的特点和他们背后的世界。
      • 查看我更新的答案,希望它能解决您对这些功能的疑问。我建议您继续 this link 以获取有关 System 课程的更多答案。
      • 也许我应该说“目的”而不是“功能”。我不想知道 Oracle 开发人员是如何实现 System 类的,而是想知道这些流是如何工作的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-06
      • 2013-05-05
      • 2010-11-19
      • 2012-06-16
      • 2011-04-02
      相关资源
      最近更新 更多