12

我有一个这样的Java类:

public class Foo {

    public static int counter = 0;

    public void bar(int counter) {
        Foo.counter = counter;
    }
}

counterFindBugs 警告我通过实例方法写入静态字段bar。但是,如果我将代码更改为:

public class Foo {

    public static int counter = 0;

    public static void setCounter(int counter) {
        Foo.counter = counter;
    }

    public void bar(int counter) {
        setCounter(counter);
    }
}

然后 FindBugs 不会抱怨。那不是错了吗?我仍在从实例方法写入静态字段,只是通过静态方法,不是吗?

4

2 回答 2

19

假设在未来的某个时候,您决定这个 setter 方法需要是线程安全的,并且您想要实现它synchronized

这段代码可以正常工作:

public synchronized static void setCounter(int counter) {
    Foo.counter = counter;
}

public void bar(int counter) {
    setCounter(counter);
}

此代码是错误的,并且会有不正确的行为:

public synchronized void bar(int counter) {
    Foo.counter = counter;
}

在这个人为的示例中,这似乎没有显着差异,尤其是因为counter通常可以标记为volatile。但是,在实际示例中,setter 方法具有更复杂的逻辑并且从许多不同的地方(不仅仅是从一个实例方法)调用,后一种模式将更容易重构。

顺便说一句,在我看来,Google 的 CodePro Analytix插件是一个比 FindBugs 更快、更全面的工具。

有关的:

于 2012-11-14T23:08:25.283 回答
5

错误描述的 FindBugs 列表中:

ST:从实例方法写入静态字段(ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD)

此实例方法写入静态字段。如果正在操纵多个实例,这很难纠正,而且通常是不好的做法。

通过从实例方法调用的静态方法访问静态字段没有类似的错误描述。

您可能想在 FindBugs邮件列表上讨论此决定背后的理由

于 2012-11-14T23:12:40.080 回答