Java 如果没有System.out,在控制台上打印怎么办?

Java 如果没有System.out,在控制台上打印怎么办?,java,io,Java,Io,最近在一次采访中,我遇到了一个问题。问题是: 假设您不能访问JDKAPI中的系统类。你不能 还可以使用ECHO。您处于JRE 5环境中。你将如何印刷 控制台上有什么吗 问题真正开始于——为什么Java给了我们PrintStream对象System.out?为什么它是最终的?没有其他方法可以在控制台上打印任何内容吗?您可以使用JDK的记录器(java.util.logging.logger) 这就是在java类中创建记录器的方法 import java.util.logging.Logger;

最近在一次采访中,我遇到了一个问题。问题是:

假设您不能访问JDKAPI中的系统类。你不能 还可以使用ECHO。您处于JRE 5环境中。你将如何印刷 控制台上有什么吗


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

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

这就是在java类中创建记录器的方法

import java.util.logging.Logger;

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

您也可以出于同样的目的使用log4j。

如果需要,您可以绕过系统对象。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();
  }
}
这一点已在中进一步阐述。

正如documantation所说

System类包含几个有用的类字段和方法。信息技术 无法实例化

所以,正如您所看到的,系统类是各种有用函数的容器。所有这些字段和方法都是静态的,因此没有任何理由对其进行扩展。
Java为我们提供了
静态打印流输出
,因为它是使用控制台与程序通信的默认方式。

如果您不同意我的意见,请告诉我。

PrintStream是最终版本,因为它完成了windows控制台/可以/完成的所有功能。在C#中,“Console”是const类也是一样的。这些类封装了控制台所能做的一切,并且只以一种特定的方式完成。你不能“让它变得更好”,因为在某一点上,它是由操作系统来处理的

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

  • 按照@eis的方式编写您自己的输出流
  • 使用JNI并调用本机DLL/中的方法,以便调用本机函数,如
    printf()
  • 使用
    Runtime.getRuntime().exec()
    并调用
    echo
    程序 清单如下
    +1到@eis

    前面提到的面试问题非常反常(即人为的),解决它需要跳出纯Java。这当然不是在正常情况下你会考虑做的事情。 其他答案给了你一些半解。。。如果你真的,真的必须这么做。(我之所以说半解决方案,是因为它们大多不处理应用程序的stdout/stderr流被重定向到控制台以外的地方的情况。这是这个问题唯一“真实”的方面…)

    如果您可以使用System类(在JDK 6上)…打印到控制台的干净方法(例如,如果
    System.out
    已重定向),则使用
    System.console()
    方法获取对象,并使用该方法获取
    写入程序

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


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

    答案是:

  • 为了方便
  • 这样,随机码就不会意外地撞击它。(如果您需要担心JVM中运行的不受信任的代码,可以故意这样做。)但受信任的代码实际上可以通过调用
    System.setOut(…)
    来更改
    System.out
    。这在幕后发挥了一些魔力,可以安全地更改
    final
    变量的状态。(我相信JIT编译器知道这一点,并以不同的方式对待这3个
    final
    变量。)
  • 对。看看上面,还有(恶心!)其他答案

  • 今天我找到了一个解决问题的方法。 我使用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!");
    
        }
    }
    

    对我来说,这听起来是一个相当奇怪的面试问题。我想知道他们到底想了解你什么。非常确定他们想了解的是,你应该使用日志框架(log4j、juli等)而不是sysout。@JonSkeet检查申请者是否知道System.out的实际功能是什么,这不是有效的吗,假设这项工作与低级的东西有关?@eis-几乎每个人都知道“System.out”实际上是怎么做的?@pap-它现在已经很老了,实际上,如果目的是向最终用户发送消息,那么日志框架就不是答案。+1;甚至不知道FileDescriptor保留对stdout、stderr、stdin的引用…回答得好。。。但是,如果标准输出被重定向,它不会帮助您写入控制台。@StephenC是的。如果只是将消息发送到控制台,并且标准输出已被重定向,则可以使用stderr,前提是尚未重定向。如果两者都被重定向,那么我认为程序不应该能够向控制台写入文本(忽略直接视频缓冲区、控制台中的旧式图形等)。@eis-但是如果我们删除人为的JDK 5/无系统限制,那么就有一个解决方案。@StephenC如果您提到System.console().writer(),也会这样做。如果stdout已被重定向(如),它将不会帮助您。我认为只有在System.out被更改的情况下它才有帮助。假设你不能访问Jdk API中的System类,这是OP所说的。你不能访问“System”类@StephenCConsole类是在Jdk 6中引入的,所以我想我们不能使用它,因为我们有Jdk5@KDjava-很明显,我在这里谈论的是切实可行的解决方案。如果一个开发/生产车间已经把自己画进了一个有生命终结的JVM的角落。。。生活是痛苦的。如果“应用程序的stdout/stderr流已重定向到控制台以外的其他位置”,System.console()也将无法工作,因此这个答案是错误的。