Java相当于python的"with"

Pet*_*ter 3 python java with-statement

Python有一个很好的功能:"with"语句.它对于进行影响语句中调用的所有代码的全局更改很有用.

例如,你可以定义一个CapturePrintStatements类来捕获在"with"中调用的所有print语句

with CapturePrintStatements() as c:
    print 'Stuff Done'
print 'More Stuff Done'
assert c.get_text() == 'Stuff Done'
Run Code Online (Sandbox Code Playgroud)

Java中是否存在等价物?

Moh*_*uag 8

try-with-resources是Java的等价物,可以在Java 7及更高版本中使用.

这使您可以使用需要明确关闭的资源,而无需担心关闭它们.例如:

在Java7之前:

InputStream input = null;

try {
    input = new FileInputStream("myFile.txt");

} finally {
    if(input != null){
        input.close();
    }
}
Run Code Online (Sandbox Code Playgroud)

Java 7及以上版本:

try(FileInputStream input = new FileInputStream("myFile.txt")) {
    // Do something with the InputStream
}
Run Code Online (Sandbox Code Playgroud)

这是try-with-resources构造.当执行流程离开try块时,FileInputStream自动关闭.这是因为FileInputStream实现了AutoCloseable接口.

  • 包括代码示例,而不仅仅是链接. (4认同)

bra*_*zzi 5

正如Mohammed指出的,您可以使用try-with-resources。在这种情况下,您希望拥有自己的资源,这并不是很难做到的。

创建一个自动关闭的类

首先,您的课程应实现AutoCloseable

public class CaptureOutput implements AutoCloseable {
Run Code Online (Sandbox Code Playgroud)

在构造此类时,您应该

这是我们的方法

    public CaptureOutput() {
        this.stream = new ByteArrayOutputStream();
        this.out = System.out;

        System.setOut(new PrintStream(stream));
    }
Run Code Online (Sandbox Code Playgroud)

秘诀就是AutoCloseable.close()方法:您只需在此处撤消替换即可:

    public void close() throws Exception {
        System.setOut(this.out);
    }
Run Code Online (Sandbox Code Playgroud)

最后,您需要一种方法来检索内容:

    public String getContent() {
        return this.stream.toString();
    }
Run Code Online (Sandbox Code Playgroud)

使用尝试资源

完成后,只需将传递CaptureOutputtry子句即可。例如下面的代码...

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);
}
Run Code Online (Sandbox Code Playgroud)

...将导致以下结果:

This will be printed
This will be printed, too.
The content of the string is EXAMPLE
Run Code Online (Sandbox Code Playgroud)

范围问题

请注意,我们不会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));
    }
Run Code Online (Sandbox Code Playgroud)

现在,我们稍后再使用流:

    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());
    }
Run Code Online (Sandbox Code Playgroud)

(此外,不可能CaptureOutputtry。之前创建变量。这很有意义: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();
        }
    
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 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());
        }
    
    }
    
    Run Code Online (Sandbox Code Playgroud)