4

假设我有一个创建对象并使用静态变量跟踪对象数量的类。像这样的东西:

public class Apple {
    private static int count = 0;

    public Apple () {
        count++;
    } 

    public void removeApple() {
        count--;
    }
}

当我使用 FindBugs 检查此代码时,我收到了警告Write to static field from instance method,这当然是显而易见的。

我怎样才能解决这个问题,让它更安全,甚至摆脱那个 FindBugs 警告?

4

4 回答 4

9

1. 一般编程建议

此消息用于警告您潜在的编程错误,因为它是初学者程序员的常见陷阱,他们不知道静态变量和实例变量范围的差异。

但是,如果您可以声明该removeApple方法的真实版本static而不会导致任何编译器错误,那么您很可能应该这样做。这既可以处理警告,也可以清楚地表明此方法与您的类的任何特定实例无关。

2. 与并发相关的问题

此警告的另一个方面涉及线程安全。如果您从实例写入static字段,则可能会从不同线程进行并发更新,即使线程之间不共享类实例也是如此。

如果您的代码不需要线程安全(这通常很好),那么您不需要做任何事情。如果您确实需要它,则同步该字段的所有更新,或使用AtomicInteger包装器。

就个人而言,我会选择它,AtomicInteger因为它是最安全的选择:其他选项需要您跟踪课堂上的所有字段更新并确保它们是同步的。使用AtomicInteger非常简单:

private static final AtomicInteger count = new AtomicInteger();

然后你使用count.getAndIncrement()而不是count++.

于 2013-07-02T10:07:06.470 回答
3

使用AtomicInteger而不是int原始的。

您可以同步该方法。

于 2013-07-02T10:03:57.700 回答
1

你有两个选择:

  1. 使用duffmyo 提到的AtomicInteger

AtomicInteger 用于诸如原子线程安全递增计数器之类的应用程序中。

或者

2. 通过同步块控制变量的访问

仅从 Findbug 错误删除的角度来看:

从逻辑上讲,我们期望实例方法会影响该实例的数据。我们期望静态方法会影响静态数据。

将计数器设为私有并提供公共 getter 和 setter 方法将消除 findbug 错误。

于 2013-07-02T10:05:25.187 回答
1

很可能 FindBugs 更喜欢 removeApple() 是静态的

于 2013-07-02T10:08:52.040 回答