【问题标题】:How to make this variable reference `final`, how do I get this to compile cleanly?如何使这个变量引用`final`,我如何让它编译干净?
【发布时间】:2011-08-20 07:29:29
【问题描述】:

我想创建result 变量final,我如何构造这段代码以便编译干净?我知道我过去曾这样做过,但我不记得我是如何构建它以使其发挥作用的。

以下代码是straw man 示例,我要清理的代码要复杂得多,这只是提炼我要完成的工作的精髓。

private boolean someMethod()
{
    final boolean result;
    try
    {
        // do the logic here that might throw the following
        // exceptions
    }
    catch (final IOException ioe)
    {
        result = false;
    }
    catch (final ClassNotFoundException cnfe)
    {
        result = false;
    }

    return result;
}

我不能将result = true 放在try 块中,因为它不会与两个抱怨最终变量可能已经分配的catch 块一起编译。

我不能将它放在 finally 块中,因为这会产生与 try 块中相同的投诉?

我希望能够将result = 设置一次且仅一次。

那么你在哪里设置result = true; 让它编译干净?

【问题讨论】:

  • 为什么要创建一个局部变量final
  • 我尽可能多地制作final,因为它使调试更加容易,记录了变量应该被分配一次且仅一次的意图,并且是一种优化在大多数情况下也会提示编译器。我没有听说过这方面的争论,我知道尽可能多地引用变量final 极大地提高了代码库的质量。
  • @Jarrod Roberson:对我来说,在这种情况下,这种“优化”会降低代码质量(即可读性)。没有理由将result 声明为final,尤其是当它会使您的方法不必要地更加复杂时。除了这种情况,我完全同意你的看法。 :)
  • 这是这个问题的稻草人,这实际上不是我想要按照我的意愿工作的代码,它不会使它变得更复杂,它使它更具可读性,并且如果我的代码中需要设置它的其他地方尝试覆盖它,编译器将捕获错误。
  • 如果我的代码中需要设置此项的其他地方尝试覆盖它,编译器会捕获错误?这是一个局部变量!

标签: java final idioms


【解决方案1】:

不设置变量要简单得多。

private boolean someMethod() {
    try {
        // do the logic here that might throw the following
        return true;

    } catch (IOException ioe) {
        // handle IOE
    } catch (ClassNotFoundException cnfe) {
        // handle CNFE
    }
    return false;
}

【讨论】:

  • 我也是这么想的。为什么要设置一个您将要返回的最终变量?从设计的角度来看,最初的例子并不适合我。
  • 这是我试图实现的目标的解决方案return 在一堆 catch 子句中不好,不可变的 result 是也不好。当我读到这个答案时,我现在记得这是我过去采取的方法,感谢您回忆起我的记忆。
【解决方案2】:

尝试使用final 来强制执行“只分配一次”总是很棘手。您可以使用第二个变量:

private boolean someMethod()
{
    boolean res;
    try
    {
        // do the logic here that might throw the following
        // exceptions
    }
    catch (final IOException ioe)
    {
        res = false;
    }
    catch (final ClassNotFoundException cnfe)
    {
        res = false;
    }
    final boolean result = res;
    return result;
}

但真正的问题是,为什么不直接删除 final 限定符?

【讨论】:

  • 要么这个,要么删除try-catch 块并让someMethod 抛出IOExceptionClassNotFoundException
  • 这是一个文档,它应该只设置一次且只设置一次,这使得出错并有助于调试。
  • 这个答案没有达到我的目标。我不想用与其操作无关的异常来污染我的其余代码
  • @Jarrod - 我认为编译器执行的流分析不会让您在 catch 块中进行这种分配。有人可能会争辩说它应该能够这样做,但事实并非如此。我建议不要在这方面与市政厅抗争,只需将 final 声明替换为声明上方的简单评论即可。
【解决方案3】:

您不能将值重新分配给 final 变量,因此这是不可能的。

编辑:想要将一个方法的局部变量声明为final 并更改同一方法中的值也是矛盾的 - 为什么有必要在此声明为final方法?

【讨论】:

  • 我没有设置任何东西,我不想重新分配它,我想只分配一次,要么分配给true要么@ 987654325@.
  • 但是final 意味着您只能在与声明相同的语句中分配一次 - 因此它不能被声明然后在这样的块中分配。为什么不直接从声明中删除 final 修饰符,看看这只是一个局部变量?
【解决方案4】:

如果在方法中将局部变量声明为final,则该变量的值不能在方法中更改。

result 的声明中删除final,或者完全去掉result 局部变量,直接从catch 块内和方法的末尾返回。

【讨论】:

  • 从一堆catch 块中返回是一种糟糕的做法。
  • 从一个方法中的多个地方返回是不好的做法,它是GOTO的反面,因此从多个catch块返回是不好的做法。
  • 一本有趣的书,谢谢。不过,这并不是我的答案中最重要的一点,就像彼得在他接受的答案中所建议的那样,删除 final 或完全删除 result 本地。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-28
相关资源
最近更新 更多