【问题标题】:java: how to declare final a variable that is initialized inside a try - catch block?java:如何声明一个在try-catch块中初始化的变量?
【发布时间】:2012-02-19 15:45:28
【问题描述】:

我有一个变量在初始化后不应该改变它的值,所以我想将它定义为最终变量。

问题是变量必须在try块中初始化,所以我遇到了以下麻烦:

我有以下代码:

Connection conn = null;
try {
    conn = getConn(prefix);
    [...do some stuff with conn...]
} catch (Exception e) {
    throw new DbHelperException("error opening connection", e);
} finally {
    closeConnection(conn);
}

如果我将变量声明为 final,而不将其初始化为 null,我会在 finally 块上得到“局部变量 conn 可能尚未初始化”。另一方面,如果我将其声明为 final 并将其初始化为 null,则会在 try 块中收到错误“无法分配最终局部变量 conn”。

编辑:lxx 回答后,我使用了这个版本

try {
    final Connection conn = conn = getConn(prefix);
    try {
        return selectAll(conn, sql, params);
    } catch (Exception e) {
        throw new DbHelperException("error executing query", e);
    } finally {
        closeConnection(conn);  
    }
} catch (Exception e) {
    throw new DbHelperException("error opening connection", e);
}

所以这应该是这样做的方式吗?

--

经验教训:

我认为这个问题的正确答案是 lxx 给出的答案,但在这种情况下,我想声明变量 final 的弊端超过了它的好处......

--

编辑:发现关于何时使用 final 的堆栈溢出的两个问题

When should one use final for method parameters and local variables?

Using "final" modifier whenever applicable in java

【问题讨论】:

  • final Connection finalConn = conn; 附加到您的代码中怎么样?
  • 为什么你需要两个trys?为什么不只使用一个 try-catch 来获取连接并使用它来全选?
  • 我会质疑为什么您认为将其宣布为最终结果如此重要。对我来说,这似乎相当保姆和唠叨。如果我是用户,并且我调用了您的方法来建立连接,那么我看不出有任何理由要通过更改它来搞砸它。如果我这样做了,我认为后果应该由用户承担。
  • 同意达菲莫。对于如此短的代码块中的局部变量,final 是没有必要的。
  • yshavit:这两次尝试都是我发现的方式 - 感谢 lxx- 将变量保持为最终...

标签: java try-catch final


【解决方案1】:

您可以更准确地处理异常。如果您在打开连接时遇到异常,我猜您不必在 finally 块中关闭它。如果之后在 try 块中遇到异常,并在新的嵌套 try-catch 块中处理异常,则无需在外部定义变量。比如:

    try {
        final Connection conn = getConn(prefix);
        try {
            //code using conn
        } catch (Exception e) {

        } finally {
            closeConnection(conn);
        }
    } catch (DbHelperException e) {
        throw new DbHelperException("error opening connection", e);
    }

【讨论】:

  • 是的,我明白你的意思了,我假设如果有异常打开连接,连接无法打开,所以没有必要关闭它。我带来了另一个版本的代码,感谢您的回答,再次检查问题...
  • @opensas 如果getConn()调用出现异常,无论连接是否真的打开,conn肯定为空,所以无论如何你都无法关闭它.
  • 在需要外层try catch的时候这样就好了,但是当我不需要外层try catch时,我该怎么办?
【解决方案2】:

这个怎么样?

Connection temp = null;
try {
    temp = getConn(prefix);
} catch (Exception e) {
    throw new DbHelperException("error opening connection", e);
} finally {
    closeConnection(conn);
}
final Connection conn = temp;

【讨论】:

  • 您也可以继续将 temp 设置回 null 这样您就不再使用它了。
  • 这是获取已关闭连接的final 引用的好方法。 :)
  • @Michael 让 JVM 来处理它。
【解决方案3】:

你为什么想要它最终?如果你想将它传递给匿名内部类,你可以这样做:

Connection conn = null;
try {
    conn = getConn(prefix);
    final Connection finalConn = conn;
    // pass it to inner class here
} catch (Exception e) {
    throw new DbHelperException("error opening connection", e);
} finally {
    closeConnection(conn);
}

此解决方案的唯一问题(也是一个相当大的问题)是您离开此块后立即关闭连接。所以除非你立即声明并调用你的匿名内部类,否则这种模式是行不通的。

无论哪种方式,如果我是你,我可能会改写整个事情,将 prefix 设为 final 并将连接处理委托给匿名内部类。

【讨论】:

  • 哎呀!你是对的,(顺便说一句,你发现了一个讨厌的错误,谢谢) - 更新了问题......
  • 我想将它定义为final,只是为了告诉编译器变量conn在初始化后不应该改变它的值......
【解决方案4】:

您可以尝试在 catch 和 finally 块中分配它吗? 像这样:

Connection connTemp = null;
final Connection conn;
try {
    connTemp = getConn(prefix);
} catch (Exception e) {
    throw new DbHelperException("error opening connection", e);
} finally {
    closeConnection(conn);
}
conn = connTemp;

【讨论】:

  • 一旦声明为 final 就不能在任何地方更改,这就是目的
  • 将其更新为使用临时变量。
猜你喜欢
  • 2014-06-23
  • 1970-01-01
  • 2014-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多