Python 有一个很好的特性:“with”语句。它对于进行影响语句中调用的所有代码的全局更改很有用。
例如您可以定义一个类 CapturePrintStatements 来捕获在“with”中调用的所有打印语句
with CapturePrintStatements() as c:
print 'Stuff Done'
print 'More Stuff Done'
assert c.get_text() == 'Stuff Done'
Java 中是否有等效项?
最佳答案
正如 Mohammed 所说,您可以使用 try-with-resources。在这种情况下,你想要拥有自己的资源,其实并不难。
创建一个可自动关闭的类
首先,您的类应该实现AutoCloseable
:
public class CaptureOutput implements AutoCloseable {
在构造这个类的时候,你应该
- 存储旧的
System.out
, - 创建一个
PrintStream
来替换它(参见 Java: PrintStream to String? )和 - 用
System.setOut()
替换默认流。
这是我们的做法
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
block 完成,它就消失了。[1]这就是我们从 block 内部获取值的原因。
没那么优雅吧?一个解决方案可能是将 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
对象应该是使用后“关闭”。毕竟,关闭的文件有什么用?我们的用例与它有点不同,因此我们必须依赖替代方案。)
完整类(class)
这里是完整的类(class):
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()); } }
关于Java相当于python的 "with",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35116227/