【问题标题】:How can I write to a static field safely in Java?如何在 Java 中安全地写入静态字段?
【发布时间】:2013-07-02 10:02:12
【问题描述】:

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

public class Apple {
    private static int count = 0;

    public Apple () {
        count++;
    } 

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

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

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

【问题讨论】:

标签: java static warnings instance findbugs


【解决方案1】:

1。一般编程建议

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

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

2。与并发相关的问题

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

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

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

private static final AtomicInteger count = new AtomicInteger();

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

【讨论】:

  • 不也可以使用同步方法吗?
【解决方案2】:

使用AtomicInteger 代替int 原语。

你可以同步方法。

【讨论】:

    【解决方案3】:

    你有两个选择:

    1. 使用 duffmyo 提到的AtomicInteger

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

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

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

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

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • +1 这也是一个相当合理的设计决定,除非 OP 的代码只是一个缩减示例。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-14
      • 2010-12-21
      • 2014-09-16
      • 1970-01-01
      相关资源
      最近更新 更多