Java:如何让 lint 遵守内部函数调用抛出的 RuntimeException?

Java: How to make lint respect the RuntimeException thrown from a inner function call?

我正在使用 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 检查器报告 o 可能尚未初始化的错误。 显然,当转到 else 分支时,会抛出 IllegalStateExceptionRuntimeException 的子类),因此执行已终止。

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

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

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

皮棉是正确的。考虑到 "panic" 将来可能会被更改,或者被子类覆盖而不抛出异常。 o 将未初始化。如果你真的想让 lint 闭嘴,只需初始化它。

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

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

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

局部变量必须明确赋值

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

For every access of a local variable or blank final field x, x must be definitely assigned before the access, or a compile-time error occurs.

可以做什么

重新定义panic()

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

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

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

panic() 方法可以执行额外的工作,尽管不鼓励记录 然后 抛出异常,因为它往往会导致冗余记录。