我一直被最近在一次采访中被问到的一个问题所困扰。问题表述为:
假设您无权访问 Jdk API 中的 System 类。您也不能使用 ECHO。您处于 JRE 5 环境中。您将如何在控制台上打印任何内容?
这个问题真正开始于 - 为什么 Java 给了我们PrintStream
对象System.out
?为什么它是最终的?没有其他方法可以在控制台上打印任何内容吗?
如果你愿意,你可以绕过 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();
}
}
此处已对此进行了更详细的阐述。
PrintStream 是最终的,因为它完成了 Windows 控制台 /can/ 所做的一切。同样,“控制台”是 C# 中的 const 类。这些类封装了控制台可以做的所有事情,而且它只以一种特定的方式做。您不能“让它变得更好”,因为在某一时刻,由操作系统来处理它。
有很多方法可以在屏幕上输出内容:
printf()
Runtime.getRuntime().exec()
调用echo
程序,列表如下。+1 到@eis
您可以使用JDK 的记录器(java.util.logging.Logger)。
这就是您在 java 类中创建记录器的方式。
import java.util.logging.Logger;
private final static Logger LOGGER = Logger.getLogger(MyClass.class .getName());
您也可以将 log4j 用于相同目的。
如上所述的面试问题是非常不正当的(即人为的),解决它需要跳出纯Java。这当然不是您在正常情况下会考虑做的事情。
其他答案给了你一些半解决方案......如果你真的,真的必须这样做。(我说半解决方案是因为它们大多不处理应用程序的 stdout / stderr 流被重定向到控制台以外的其他地方的情况。这是这个问题的唯一“真实”方面......)
如果您可以使用 System 类(在 JDK 6 上)...打印到控制台的干净方式(例如,如果System.out
已被重定向)是使用System.console()
方法获取Console
对象,并使用该方法获取Writer
.
但是请注意,如果 JVM 没有关联的控制台,console()
将返回null
.
问题的真正开始是——为什么 Java 给了我们 PrintStream 对象 System.out ?为什么它是最终的?没有其他方法可以在控制台上打印任何内容吗??
答案是:
System.out
调用System.setOut(...)
. 这在幕后做了一些魔术来安全地更改final
变量的状态。(我相信 JIT 编译器意识到了这一点,并以final
不同的方式处理这 3 个变量。)正如文档所说,
System 类包含几个有用的类字段和方法。它不能被实例化。
因此,如您所见,System 类是不同有用功能的容器。所有这些字段和方法都是静态的,因此没有任何理由扩展它。
Java 提供给我们static PrintStream out
是因为它是与程序通信的默认方式——使用控制台。
如果你不同意我的观点,请告诉我。
我今天找到了解决这个问题的方法。我正在使用 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!");
}
}