Java 8 - 有效的最终变量,lambdas和try / catch / finally块

时间:2016-03-11 00:03:32

标签: java lambda try-catch finally

所以我开始玩Java 8流/ lambda表达式,遇到了一些有趣的问题,我不确定如何解决。我在这里,请你帮忙。

有问题的示例代码:

public void insertBlankPages(File inputFile, String outputFile, final int OFFSET) {
    PDDocument newDocument;
    PDDocument oldDocument;
    try {
        newDocument = createNewDocument();
        oldDocument = createOldDocument(inputFile);
        List<PDPage> oldPages = getAllPages(oldDocument);

        oldPages.stream()
                .limit(oldPages.size() - OFFSET)
                .forEach(page -> {
                    newDocument.addPage(page);
                    newDocument.addPage(new PDPage(page.getMediaBox()));
                });

        newDocument.save(outputFile);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (COSVisitorException e) {
        e.printStackTrace();
    } finally {
        newDocument.close();
        oldDocument.close();
    }
}

使用上面的代码,编译器会抱怨finally块中对close()的调用。错误是:&#34;变量newDocument可能尚未初始化&#34;。对于oldDocument也是如此。

当然,我继续将变量初始化如下:

PDDocument newDocument = null;
PDDocument oldDocument = null;

现在我遇到编译器错误&#34; lambda表达式中使用的变量应该是有效的最终版本&#34;。

如何解决这个问题?

方法createNewDocument和createOldDocument抛出异常,因此调用必须在try / catch块中。我还需要关闭finally块中的文档。

我应该可以通过使用try-with-resources来解决这个问题。但是,我很想知道是否还有其他适当的解决办法。

感谢。

3 个答案:

答案 0 :(得分:2)

正确的解决方案是尝试资源。

如果没有这个,你需要手动嵌套一些try / finally块:

try {
    PDDocument newDocument = createNewDocument();
    try{           
       PDDocument oldDocument = createOldDocument(inputFile);
       try{
          // .....
       }
       finally { oldDocument.close() }
    }
    finally{ newDocument.close(); }
}
catch (IOException e) {
    e.printStackTrace();
} 

答案 1 :(得分:1)

感谢大家的想法。似乎没有&#34;好的&#34;没有尝试资源的方式做到这一点。以下是使用try-with-resources的示例。

public void insertBlankPages(File inputFile, String outputFile, final int OFFSET) {
    try (PDDocument newDocument = createNewDocument();
         PDDocument oldDocument = createOldDocument(inputFile)) {

        List<PDPage> oldPages = getAllPages(oldDocument);

        oldPages.stream()
                .limit(oldPages.size() - OFFSET)
                .forEach(page -> {
                    newDocument.addPage(page);
                    newDocument.addPage(new PDPage(page.getMediaBox()));
                });

        newDocument.save(outputFile);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (COSVisitorException e) {
        e.printStackTrace();
    }
}

答案 2 :(得分:0)

简单的解决方法是使用数组,它本身是最终的,因此您可以在lambda中引用它,但其内容可以自由更改。

此代码与您的代码基本相同,但没有编译错误:

public void insertBlankPages(File inputFile, String outputFile, final int OFFSET) {
    PDDocument[] newDocument = new PDDocument[1]; // automatically filled with a null
    PDDocument oldDocument = null;
    try {
        newDocument[0] = createNewDocument();
        oldDocument = createOldDocument(inputFile);
        List<PDPage> oldPages = getAllPages(oldDocument);

        oldPages.stream()
                .limit(oldPages.size() - OFFSET)
                .forEach(page -> {
                    newDocument[0].addPage(page);
                    newDocument[0].addPage(new PDPage(page.getMediaBox()));
                });

        newDocument[0].save(outputFile);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (COSVisitorException e) {
        e.printStackTrace();
    } finally {
        if (newDocument[0] != null)
            newDocument[0].close();
        if (oldDocument != null)
            oldDocument.close();
    }
}