正如Mohammed所指出的,您可以使用try-with-resources。在这种情况下,您想要拥有自己的资源,这并不是很难做到。
创建一个可自动关闭类
首先,您的类应该实现AutoCloseable
:
public class CaptureOutput implements AutoCloseable {
构造此类时,您应该:
下面是如何实现的:
public CaptureOutput() {
this.stream = new ByteArrayOutputStream();
this.out = System.out;
System.setOut(new PrintStream(stream));
}
秘诀在于AutoCloseable.close()
方法:您只需在那里撤消替换:
public void close() throws Exception {
System.setOut(this.out);
}
最后,您需要一种检索内容的方法:
public String getContent() {
return this.stream.toString();
}
使用try-with-resources
做到这一点,只需将CaptureOutput
传递给try
子句。例如下面的代码...
public static void main(String[] args) throws Exception {
String content = null;
System.out.println("This will be printed");
try (CaptureOutput co = new CaptureOutput()) {
System.out.println("EXAMPLE");
content = co.getContent();
}
System.out.println("This will be printed, too.");
System.out.println("The content of the string is " + content);
}
这将导致以下结果:
This will be printed
This will be printed, too.
The content of the string is EXAMPLE
作用域问题
请注意,我们在最后一行不调用 co.getContent()
。这是不可能的,因为与 Python 不同,co
变量的作用域仅限于 try
代码块中。一旦 try
块结束,它就消失了[1]。这就是为什么我们从块内获取值。
不太优雅,是吧?一个解决方案可能是将 BAOS 提供给 CaptureOutput
构造函数:
public CaptureOutput(ByteArrayOutputStream stream) {
this.stream = stream;
this.out = System.out;
System.setOut(new PrintStream(this.stream));
}
现在,我们稍后再使用流:
public static void main(String[] args) throws Exception {
System.out.println("This will be printed");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
try (CaptureOutput co = new CaptureOutput(stream)) {
System.out.println("EXAMPLE");
}
System.out.println("This will be printed, too.");
System.out.println("The content of the string is " + stream.toString());
}
(此外,在try
之前创建CaptureOutput
变量是不可能的。这是有道理的: AutoCloseable
对象应该在使用后被“关闭”。毕竟,关闭的文件有什么用呢?但我们的用例略有不同,因此我们必须依靠替代方法。)
完整的类
以下是完整的类:
CaptureOutput.java
:
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
public class CaptureOutput implements AutoCloseable {
private ByteArrayOutputStream stream;
private PrintStream out;
public CaptureOutput(ByteArrayOutputStream stream) {
this.stream = stream;
this.out = System.out;
System.setOut(new PrintStream(this.stream));
}
public CaptureOutput() {
this(new ByteArrayOutputStream());
}
@Override
public void close() throws Exception {
System.setOut(this.out);
}
public String getContent() {
return this.stream.toString();
}
}
Main.java
:
import java.io.ByteArrayOutputStream;
public class Main {
public static void main(String[] args) throws Exception {
System.out.println("This will be printed");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
try (CaptureOutput co = new CaptureOutput(stream)) {
System.out.println("EXAMPLE");
}
System.out.println("This will be printed, too.");
System.out.println("The content of the string is " + stream.toString());
}
}