Java:如何使lint尊重从内部函数调用抛出的RuntimeException?

时间:2018-03-27 21:38:52

标签: java android-studio lint

我正在使用Android Studio编写Android代码,并在编写代码时执行自动lint检查。

我有一个这样的代码段:

Obj fun() {
    Obj o;
    if (SOME_CONDITION) {
        if (SOME_OTHER_CONDITION) {
            o = SOMETHING;
        } else {
            panic();
        }
    } else {
        panic();
    }
    return o;
}

其中panic()是另一个像这样的函数

void panic() {
    throw new IllegalStateException();
}

但是,lint检查程序报告可能尚未初始化的错误。 显然,当转到else分支时,会抛出IllegalStateExceptionRuntimeException的子类),因此执行已经终止。

注意o = SOMETHING;语句是简化描述。实际代码更复杂,并包含其他条件检查。

throws RuntimeException(或IllegalStateException)添加到panic()并没有任何区别。

如何告诉linter它不会出错(没有捕获异常并再次抛出)?

2 个答案:

答案 0 :(得分:1)

棉绒是正确的。考虑一下"恐慌"可能会在将来更改,或被子类覆盖而不是抛出异常。 o将是未初始化的。如果你真的希望lint关闭它,只需初始化它。

更好的选择是将o的声明和return语句移动到o = something的分支。这是它真正使用的唯一地方,它掩盖了代码在其他地方的真实意图。而不是在函数结束时返回,抛出异常。如果panic()确实抛出异常,那么该行将永远不会被调用,但它应该让所有人都满意。

事实上,根据您的真实代码,您可以进一步简化:

Obj fun() {
    if (SOME_CONDITION && SOME_OTHER_CONDITION) {
            return SOMETHING;
    } 
    panic();
    throw new RuntimeException("We don't expect to get here");
}

答案 1 :(得分:1)

必须明确指定局部变量

你想要的是不可能的。它不仅仅是Android studio中的linter规则,它还是编译器强制执行的语言规则。 JLS 16 states(强调补充):

  

对于本地变量或空白final字段x的每次访问,必须在访问之前明确分配x,否则会发生编译时错误。

可以做什么

重新定义panic()

RuntimeException panic() {
  return new IllegalStateException();
}

然后像这样使用它以允许编译器验证控制流永远不会导致访问未分配的变量:

...
} else {
    throw panic();
}
...

panic()方法可以执行其他工作,但不鼓励记录然后抛出异常,因为它往往会导致冗余日志记录。