Java相当于python的 "with"

标签 java python with-statement

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/

相关文章:

java - 如何使java.awt.Label背景透明?

java - double 转换为 NaN

python - 如何在不关闭资源的情况下留下 `with` block ?

python - 如何打开一堆文件(使用上下文管理)而不嵌套一堆缩进

java - 如何使用smack添加好友?

java - 如何使用 JSON API 和 CloseableHttpClient 将文件上传到 Google Cloud Storage 存储桶?

python - 仅在数据框中填充缺失值( Pandas )

python - 光标在 Tkinter 中的 matplotlib Canvas 上

python - ElasticSearch Python客户端在创建索引时如何定义分片数量

python - 长时间保持 80 个字符的边距?