7

我一直被最近在一次采访中被问到的一个问题所困扰。问题表述为:

假设您无权访问 Jdk API 中的 System 类。您也不能使用 ECHO。您处于 JRE 5 环境中。您将如何在控制台上打印任何内容?

这个问题真正开始于 - 为什么 Java 给了我们PrintStream对象System.out?为什么它是最终的?没有其他方法可以在控制台上打印任何内容吗?

4

6 回答 6

16

如果你愿意,你可以绕过 System object。System.out 做了很多额外的事情(例如处理 unicode),所以如果你真的只想要原始输出和性能,你实际上甚至可能应该绕过它。

import java.io.*;

public class PrintOutTest {
  public static void main(String args[]) throws IOException {
    BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new
      FileOutputStream(FileDescriptor.out), "ASCII"), 512);
    out.write("test string");
    out.write('\n');
    out.flush();
  }
}

此处已对此进行了更详细的阐述。

于 2012-11-01T07:43:41.577 回答
4

PrintStream 是最终的,因为它完成了 Windows 控制台 /can/ 所做的一切。同样,“控制台”是 C# 中的 const 类。这些类封装了控制台可以做的所有事情,而且它只以一种特定的方式。您不能“让它变得更好”,因为在某一时刻,由操作系统来处理它。

有很多方法可以在屏幕上输出内容:

  1. 以@eis 的方式编写您自己的 OutputStream
  2. 使用 JNI 并调用本机 DLL/SO 中的方法,该方法调用本机函数,例如printf()
  3. 使用Runtime.getRuntime().exec()调用echo程序,列表如下。

+1 到@eis

于 2012-11-01T07:49:41.837 回答
2

您可以使用JDK 的记录器(java.util.logging.Logger)。

这就是您在 java 类中创建记录器的方式。

import java.util.logging.Logger;

private final static Logger LOGGER = Logger.getLogger(MyClass.class .getName()); 

您也可以将 log4j 用于相同目的。

于 2012-11-01T07:37:51.123 回答
2

如上所述的面试问题是非常不正当的(即人为的),解决它需要跳出纯Java。这当然不是您在正常情况下会考虑做的事情。

其他答案给了你一些半解决方案......如果你真的,真的必须这样做。(我说半解决方案是因为它们大多不处理应用程序的 stdout / stderr 流被重定向到控制台以外的其他地方的情况。这是这个问题的唯一“真实”方面......)

如果您可以使用 System 类(在 JDK 6 上)...打印到控制台的干净方式(例如,如果System.out已被重定向)是使用System.console()方法获取Console对象,并使用该方法获取Writer.

但是请注意,如果 JVM 没有关联的控制台,console()将返回null.


问题的真正开始是——为什么 Java 给了我们 PrintStream 对象 System.out ?为什么它是最终的?没有其他方法可以在控制台上打印任何内容吗??

答案是:

  1. 为了方便。
  2. 这样随机代码就不会意外破坏它。(或者如果您需要担心在您的 JVM 中运行不受信任的代码,则故意这样做。)但受信任的代码实际上可以通过System.out调用System.setOut(...). 这在幕后做了一些魔术来安全地更改final变量的状态。(我相信 JIT 编译器意识到了这一点,并以final不同的方式处理这 3 个变量。)
  3. 是的。见上文,以及(糟糕!)其他答案。
于 2012-11-01T07:49:51.967 回答
1

正如文档所说,

System 类包含几个有用的类字段和方法。它不能被实例化。

因此,如您所见,System 类是不同有用功能的容器。所有这些字段和方法都是静态的,因此没有任何理由扩展它。
Java 提供给我们static PrintStream out是因为它是与程序通信的默认方式——使用控制台。
如果你不同意我的观点,请告诉我。

于 2012-11-01T07:47:48.457 回答
0

我今天找到了解决这个问题的方法。我正在使用 org.apache.log4j 来回答这个问题。正如许多人所说,还有许多其他方法。谢谢。

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;

public class HelloByLogger {

    private final static Logger logger = Logger.getLogger(HelloByLogger.class);

    public static void main(String[] args) {

        BasicConfigurator.configure();

        logger.info("From Logger... Ola!");

    }
}
于 2016-07-15T09:47:58.417 回答