正如 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());
}
}