如何在Java中安全地写入静态字段?

时间:2013-07-02 10:02:12

标签: java static warnings instance findbugs

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

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 个答案:

答案 0 :(得分:9)

1。一般编程建议

此消息是为了警告您潜在的编程错误,因为对于初学程序员来说,这是一个常见的陷阱,他们不了解静态和实例变量范围的差异。

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

2。与并发有关的问题

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

如果您的代码不需要线程安全(一般情况下完全没问题),那么您不需要做任何事情。如果确实需要,请同步该字段的所有更新,或使用AtomicInteger包装。

就个人而言,我选择AtomicInteger,因为它是最安全的选项:其他选项需要您追逐类周围的所有字段更新并确保它们已同步。使用AtomicInteger非常简单:

private static final AtomicInteger count = new AtomicInteger();

然后您使用count.getAndIncrement()代替count++

答案 1 :(得分:3)

使用AtomicInteger代替int原语。

您可以同步该方法。

答案 2 :(得分:1)

您有两种选择:

  1. 使用duffmyo提及的AtomicInteger
  2.   

    AtomicInteger用于原子等应用程序   线程安全的递增计数器。

    2。通过synchronized块控制变量的访问

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

      

    逻辑上,我们希望实例方法能够影响该实例的数据。   我们希望静态方法能够影响静态数据。

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

答案 3 :(得分:1)

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