使代码 java 1.6 兼容(-source 1.6 不支持 try-with-resources)

make code java 1.6 compatible (try-with-resources is not supported in -source 1.6)

我有以下代码与 java 1.7 兼容,但是,我需要它与 java 1.6 兼容。目前我收到此代码的以下错误:try-with-resources is not supported in -source 1.6

代码如下所示:

    try (QueryExecution qexec = QueryExecutionFactory.create(query, input.getModel())) {
        // Some other code
        while (results.hasNext()) {
            // do something
        }
        return something;
    }

我需要更改什么才能使其与 java 1.6 一起使用?

真实答案:

真正的答案是使用Java 7 或 8。 Java 6很老了。 Java7四年前出来了; Java8个,快一年半了。

只有在有非常非常好的理由不能这样做时才继续阅读。 :-)

TL;DR

那个具体的例子可以简单的是:

QueryExecution qexec = QueryExecutionFactory.create(query, input.getModel());
Throwable thrown = null;
try {
    // Some other code
    while (results.hasNext()) {
        // do something
    }
    return something;
}
catch (Throwable t) {
    thrown = t; // Remember we're handling an exception
    throw t;
}
finally {
    try {
        qexec.close();
    }
    catch (Throwable t) {
        if (thrown == null) {
            // Not handling an exception, we can rethrow
            throw t;
        }
        else {
            // Log it or something, you can't allow it to
            // throw because there's *already* an exception
            // being thrown and you'll hide it. This is why
            // Java 7 added Throwable#addSuppressed.
        }
    }
}

但那是因为这是一个非常简单的案例。如果还有任何其他资源需要关闭(例如,results?)或者您在代码本身中处理一些异常,那将更加复杂。

更一般的形式是;

SomeResource r1 = null;
Throwable thrown = null;
try {
    r1 = new SomeResource();

    SomeOtherResource r2 = null;
    try {
        r2 = new SomeOtherResource();
        // use them
        return something;
    }
    catch (Throwable t) {
        thrown = t; // Remember we're handling an exception
        throw t;
    }
    finally {
        try {
            r2.close();
        }
        catch (Throwable t) {
            if (thrown == null) {
                // Not handling an exception, we can rethrow
                throw t;
            }
            else {
                // Log it or something, you can't allow it to
                // throw because there's *already* an exception
                // being thrown and you'll hide it. This is why
                // Java 7 added Throwable#addSuppressed.
            }
        }
    }
}
catch (Throwable t) {
    thrown = t; // Remember we're handling an exception
    throw t;
}
finally {
    try {
        r1.close();
    }
    catch (Throwable t) {
        if (thrown == null) {
            // Not handling an exception, we can rethrow
            throw t;
        }
        else {
            // Log it or something
        }
    }
}

您可能需要一些实用程序库函数来帮助解决此问题,否则它是 很多 样板文件。在我知道异常已经发生的情况下,我曾经做过 "silent" 关闭的事情。


详细信息:这在 §14.20.3 of the JLS 及其小节中介绍:

一个简单的try-with-resources:

try ({VariableModifier} R Identifier = Expression ...)
    Block

转换为:

{
    final {VariableModifierNoFinal} R Identifier = Expression;
    Throwable #primaryExc = null;

    try ResourceSpecification_tail
        Block
    catch (Throwable #t) {
        #primaryExc = #t;
        throw #t;
    } finally {
        if (Identifier != null) {
            if (#primaryExc != null) {
                try {
                    Identifier.close();
                } catch (Throwable #suppressedExc) {
                    #primaryExc.addSuppressed(#suppressedExc);
                }
            } else {
                Identifier.close();
            }
        }
    }
}

您必须删除 addSuppressed 部分,因为 Throwable 在 JDK6 中没有。

扩展try-with-resources:

try ResourceSpecification
    Block
[Catches]
[Finally]

转换为:

try {
    try ResourceSpecification
        Block
}
[Catches]
[Finally]

...

try ResourceSpecification
    Block

...被简单的try-with-resources变成的大东西代替了,所以整个东西变成:

try {
    {
        final {VariableModifierNoFinal} R Identifier = Expression;
        Throwable #primaryExc = null;

        try ResourceSpecification_tail
            Block
        catch (Throwable #t) {
            #primaryExc = #t;
            throw #t;
        } finally {
            if (Identifier != null) {
                if (#primaryExc != null) {
                    try {
                        Identifier.close();
                    } catch (Throwable #suppressedExc) {
                        #primaryExc.addSuppressed(#suppressedExc);
                    }
                } else {
                    Identifier.close();
                }
            }
        }
    }
}
[Catches]
[Finally]

...这就是我们如此喜欢 try-with-resources 语句的原因。

what do I need to change in order to make it work with java 1.6?

试试下面的代码:

QueryExecution qexec = null; 
try {
  qexec = QueryExecutionFactory.create(query, input.getModel()));
  // Some other code
  while (results.hasNext()) {
      // do something
  }
  return something;
} finally {
    if (qexec != null){
        qexec.close();
    }
}

最重要的部分:必须在 finally 块中手动关闭流。

但是请注意,Oracle Java SE 6 甚至现在的 Oracle Java SE 7 都达到了 EoL。因此,如果您使用的是 Oracle 的实施并且没有相应的支持合同,那么强烈建议升级到 Java SE 8