为局部变量赋值配置 CheckStyle 而不是 final

Configure CheckStyle instead of final for local variable assignment

我可以将 CheckStyle 配置为在分配局部变量时出错(初始化除外)吗? 基本上默认情况下使所有局部变量成为最终变量,而不必在其中放入大量 final 关键字代码。

在 Java 中声明一个局部变量 final 将确保它在初始化后永远不会被赋值。这非常有用,可以更轻松地推理代码。我认为除非有某些特定原因,否则所有变量都应该是最终的。可悲的是,在 Java 中,这要求我将 final 放在一切前面,恕我直言,这会不必要地使代码膨胀。

我注意到 CheckStyle can error on assignment to parameters of functions。这意味着我不必再将 final 放在它们前面。有没有办法让 CheckStyle 对任何其他局部变量赋值(初始化除外)给出类似的错误?这样我就不需要将所有内容都标记为最终的。

我只看到a rule that forces me to put final for variables that can be marked as such.

如果出于某种原因您想多次分配给一个变量,您只需在该行添加注释以禁用 CheckStyle。这有点像其他语言,基本上默认情况下所有变量都是最终的,你必须使用一个特殊的关键字来使其可赋值。

PS:我也愿意在 Java 中使用其他方法在没有 CheckStyle 的情况下实现此目的。

无法开箱即用。我还检查了 Sevntu Checkstyle(一个带有额外检查的库),它通常有我需要的东西,但它似乎没有任何东西。我已经链接到支票,所以你可以自己看看,以防我遗漏任何东西。

这意味着您必须 write the check yourself. It shouldn't be overly difficult. I would copy the code for FinalLocalVariable 这已经完成了大部分繁重的工作:它已经在寻找永不改变的局部变量,您只需要确保每个变量都是这样。

如果您这样做,可以考虑向 Checkstyle 或 Sevntu 发出拉取请求。

或者,如果您只是反对使用 final 因为它太冗长,您可以考虑使用 Lombok 的 val(如 Java 10 的 var 但隐式最终- 并且在 Java 10) 之前可用。但是,如果其他开发人员正在处理您的代码库,则很难将其用作构建的一部分(不编写您试图避免的检查)。

听起来你只是想禁止重新分配。目前尚不清楚是否要禁止非最终变量,例如在 incremenent/decrement 变量的 for 循环中,所以我假设您仍然希望允许它。这可以通过 IllegalTokenCheck and XPath suppressions.

来完成

示例:

$ cat TestClass.java
public class TestClass {
    int field = 0;

    void method() {
int a = 0;
a = 1;
a += 1;
a -= 1;
a *= 1;
a /= 1;
a <<= 1;
a >>= 1;
a >>>= 1;
a++;
a--;
++a;
--a;
for (int a= 0; a < 5; a++) {}
    }
}

$ cat TestConfig.xml
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
          "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
          "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">

<module name="Checker">
    <property name="charset" value="UTF-8"/>

    <module name="TreeWalker">
<module name="IllegalToken">
  <property name="tokens" value="ASSIGN, PLUS_ASSIGN, MINUS_ASSIGN, STAR_ASSIGN, DIV_ASSIGN, SL_ASSIGN, SR_ASSIGN, BSR_ASSIGN, POST_INC, POST_DEC, INC, DEC"/>
</module>
<module name="SuppressionXpathSingleFilter">
  <property name="checks" value="IllegalToken"/>
  <property name="query" value="//VARIABLE_DEF/ASSIGN"/>
</module>
<module name="SuppressionXpathSingleFilter">
  <property name="checks" value="IllegalToken"/>
  <property name="query" value="//LITERAL_FOR/FOR_ITERATOR//*"/>
</module>
    </module>
</module>

$ java -jar checkstyle-8.18-all.jar -c TestConfig.xml TestClass.java
Starting audit...
[ERROR] TestClass.java:6:3: Using '=' is not allowed. [IllegalToken]
[ERROR] TestClass.java:7:3: Using '+=' is not allowed. [IllegalToken]
[ERROR] TestClass.java:8:3: Using '-=' is not allowed. [IllegalToken]
[ERROR] TestClass.java:9:3: Using '*=' is not allowed. [IllegalToken]
[ERROR] TestClass.java:10:3: Using '/=' is not allowed. [IllegalToken]
[ERROR] TestClass.java:11:3: Using '<<=' is not allowed. [IllegalToken]
[ERROR] TestClass.java:12:3: Using '>>=' is not allowed. [IllegalToken]
[ERROR] TestClass.java:13:3: Using '>>>=' is not allowed. [IllegalToken]
[ERROR] TestClass.java:14:2: Using '++' is not allowed. [IllegalToken]
[ERROR] TestClass.java:15:2: Using '--' is not allowed. [IllegalToken]
[ERROR] TestClass.java:16:1: Using '++' is not allowed. [IllegalToken]
[ERROR] TestClass.java:17:1: Using '--' is not allowed. [IllegalToken]
Audit done.
Checkstyle ends with 12 errors.

您可以注意到示例中没有禁止变量赋值,也没有禁止 for 循环。

如果您将变量初始化与其声明分开,这将不起作用。