System.out到底是什么?

8

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

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

据我所知,System.out并不代表控制台。它代表可以由任何需要显示它的内容处理的数据。 我是对的吗?

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

10
现代操作系统中(包括一些旧的操作系统),进程与三个标准“流”相关联:
- 标准输入:基于流的输入(stdin) - 标准输出:基于流的输出(stdout) - 标准错误:基于流的错误输出(stderr)
它们被称为标准流
默认情况下,System.in、System.out和System.err是Java用于写入这些流的标准机制。
从命令行调用的程序在命令行中的按键会进入stdin,并且stdout和stderr的输出都会显示为控制台中的文本。它们可以重定向到文件等。
通过GUI启动的程序通常没有将这些流连接到任何可见的地方。
我之前说“默认情况下”,是因为你可以使用System上的调用来更改这些流指向的位置(它们有创意的名称,比如setInsetOutsetErr)。

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

那里存在一个错误的相关性:可运行的jar文件不会导致你看不到流。如果在命令行上运行可运行的jar文件,你将看到其标准输出。

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


从命令行调用的程序是否具有重定向流,因为控制台本身是一个应用程序,它使用与任何其他应用程序一样的正常Java进程API启动这些流程? - spongebob
1
@FrancescoMenzani:从命令行调用的程序通常不会有重定向流。比如你执行java -r runnable.jar:操作系统运行java程序,并提供其标准流。java程序加载jar并设置流,以便在新加载的JVM中为System读取和输出来自操作系统的流。最终完成工作。 - T.J. Crowder
如果它们没有重定向流,那么控制台如何处理它们的IO呢? - spongebob
1
@FrancescoMenzani:在那个意义上,我不会使用“redirected”。控制台的流被提供给它启动的子进程(每当一个进程启动一个子进程时,这是标准的操作系统行为)。然后,“java”工具使得这些流对正在运行的代码可用。对我来说,这不是重定向,但这可能是一个语义上的问题。(顺便感谢您的编辑;我总是拼错...corro...um...那个词。) - T.J. Crowder

4
在这里,“System.out”代表输出流 - 输出将要去的地方。默认情况下,它设置为控制台。但是你可以将其更改为其他选项,比如文本文件。在大型应用程序中,通常用于记录日志(通常由新手程序员实现,不是一个好主意)。在这种情况下,你可以在适当的日志文件中查看输出内容。

3

Systemjava.lang包(Java中的默认包)中的final类,无法实例化。

outSystem类的静态成员字段,类型为PrintStream,其访问修饰符为public final

printlnPrintStream类的重载方法。 println将参数打印到标准控制台并换行。有多个带有不同参数的println重载方法。每个println都会调用print方法并添加一个换行符。在内部,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将允许您写入指定的文件或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();
  }
}

虽然语法可能是正确的,但我的问题不是关于语法。我想了解类的特性以及它们背后的世界。 - spongebob
请查看我的更新答案,希望能够解决你对功能的怀疑。我建议您访问此链接(http://docs.oracle.com/javase/7/docs/api/java/lang/System.html) 以获取更多有关System类的答案。 - burglarhobbit
也许我应该说“目的”而不是“特性”。我不想知道Oracle开发人员如何实现System类,而是想知道这些流是如何工作的。 - spongebob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接