Java 相当于 python 的 "with"
Java equivalent to python's "with"
Python 有一个很好的特性:"with" 语句。它对于进行影响语句中调用的所有代码的全局更改很有用。
例如您可以定义一个 class CapturePrintStatements 来捕获在 "with"
中调用的所有打印语句
with CapturePrintStatements() as c:
print 'Stuff Done'
print 'More Stuff Done'
assert c.get_text() == 'Stuff Done'
在Java中有对应的吗?
try-with-resources 是它的 Java 等价物,在 Java 7 及更高版本中可用。
这使您可以处理需要明确关闭的资源,而不必担心关闭它们。例如:
之前 Java7:
InputStream input = null;
try {
input = new FileInputStream("myFile.txt");
} finally {
if(input != null){
input.close();
}
}
Java 7 岁及以上:
try(FileInputStream input = new FileInputStream("myFile.txt")) {
// Do something with the InputStream
}
这是 try-with-resources 结构。当执行流离开 try
块时,FileInputStream
将 自动关闭 。这是因为 FileInputStream
实现了 AutoCloseable
接口。
正如 Mohammed 所说,您可以使用 try-with-resources。在这种情况下,你想拥有自己的资源,其实并不难。
正在创建可自动关闭的 class
首先,您的 class 应该实施 AutoCloseable
:
public class CaptureOutput implements AutoCloseable {
构建这个class时,你应该
- 存储旧的
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
块完成后,它就消失了。[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
对象应该在它们之后 "closed"使用。毕竟,关闭文件有什么用?我们的用例与那个有点不同,所以我们必须依赖替代方案。)
完整的 classes
这里是完整的 classes:
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());
}
}
Python 有一个很好的特性:"with" 语句。它对于进行影响语句中调用的所有代码的全局更改很有用。
例如您可以定义一个 class CapturePrintStatements 来捕获在 "with"
中调用的所有打印语句with CapturePrintStatements() as c:
print 'Stuff Done'
print 'More Stuff Done'
assert c.get_text() == 'Stuff Done'
在Java中有对应的吗?
try-with-resources 是它的 Java 等价物,在 Java 7 及更高版本中可用。
这使您可以处理需要明确关闭的资源,而不必担心关闭它们。例如:
之前 Java7:
InputStream input = null;
try {
input = new FileInputStream("myFile.txt");
} finally {
if(input != null){
input.close();
}
}
Java 7 岁及以上:
try(FileInputStream input = new FileInputStream("myFile.txt")) {
// Do something with the InputStream
}
这是 try-with-resources 结构。当执行流离开 try
块时,FileInputStream
将 自动关闭 。这是因为 FileInputStream
实现了 AutoCloseable
接口。
正如 Mohammed 所说,您可以使用 try-with-resources。在这种情况下,你想拥有自己的资源,其实并不难。
正在创建可自动关闭的 class
首先,您的 class 应该实施 AutoCloseable
:
public class CaptureOutput implements AutoCloseable {
构建这个class时,你应该
- 存储旧的
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
块完成后,它就消失了。[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
对象应该在它们之后 "closed"使用。毕竟,关闭文件有什么用?我们的用例与那个有点不同,所以我们必须依赖替代方案。)
完整的 classes
这里是完整的 classes:
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()); } }