【问题标题】:What's the best way to fix this 'write to static field from instance method' findbugs warning?修复此“从实例方法写入静态字段”findbugs 警告的最佳方法是什么?
【发布时间】:2011-04-07 12:38:01
【问题描述】:

我有一个看起来与此类似的类,而 findbugz 抱怨“从实例方法写入静态字段”(initialize()killStaticfield())。我无法在 ctor 中设置静态字段。

  • 解决此问题的最佳方法是什么?
  • 将 staticField 放入 AtomicReference 就足够了吗?

     public class Something
     {
      private static SomeClass staticField = null;
      private AnotherClass aClass;
      public Something()
      {
    
      }
    
      public void initialize()
      {
        //must be ctor'd in initialize
        aClass = new AnotherClass();
        staticField = new SomeClass( aClass );
      }
    
      public void killStaticField()
      {
       staticField = null;
      }
    
      public static void getStaticField()
      {
        return staticField;
      }
    }
    

【问题讨论】:

  • 为了回答您的问题,这个字段是静态的,因为 get 方法需要是静态的,这样其他对象才能访问 staticField 而无需引用 Something 对象。
  • 基本上,我的问题是修复“从实例方法写入静态字段”findbugz 警告的最佳方法是什么;我只是编写了代码来表示警告。将静态对象包装在 AtomicReference 对象中更好还是同步更好?

标签: java findbugs


【解决方案1】:

问题是你想用静态字段做什么。如果它针对您创建的每个类都发生了变化,那么让它完全静态可能不是一个好主意。如果它只被初始化一次,你应该懒惰地把它初始化为一个单例。

public class Something
{
    private static SomeClass staticField = null;

    public Something()
    {

    }

    public static SomeClass getStaticField()
    {
        if(staticField == null)
            staticField = new SomeClass();;
        return staticField;
    }
}

【讨论】:

  • 别忘了让getStaticField方法synchronized
  • 请注意,您不能只将 synchronized 放在静态方法定义上,因为静态方法使用 Something.class 进行同步!
  • 我认为在讨论任何高级线程问题之前应该清楚静态变量的使用。抱歉,但您的问题听起来并不像您了解何时使用静态变量以及何时不使用。也许您可以再澄清一下您的问题。
  • @darrickc 在课堂上同步有什么问题?如果您的班级只是一个单身持有者(如您的示例),那么这是一个不错的同步解决方案。
【解决方案2】:

如果 staticField 不应该是静态的,则从 staticField 中删除它。

将 kill 和 getStaticField 设为静态。而且您通常通过类名而不是(隐式) this 来引用静态,以非常清楚地表明它是静态的,并且可能会在其他线程中导致意想不到的后果。

如有疑问,请勿对非常量字段使用静态。

【讨论】:

  • 您不需要“有疑问时”。
【解决方案3】:

尽可能接近您的原始设计...

public class Something {
  private static volatile SomeClass staticField = null;

  public Something() {
  }

  public static SomeClass getStaticField() {
    if(Something.staticField == null)
      Something.staticField = new SomeClass();;
    return Something.staticField;
  }
}

通过类名引用您的静态变量,这将删除 findbugz 警告。 将您的静态变量标记为 volatile,这将使引用在多线程环境中更安全。

更好的是:

public class Something {
  private static final SomeClass staticField = new SomeClass();

  public Something() {
  }

  public static SomeClass getStaticField() {
    return Something.staticField;
  }
}

【讨论】:

  • 但是没有同步的设计也意味着没有killStaticField。
  • 你知道...看看第一个解决方案,它仍然不是线程安全的,即使变量是可变的。您必须在 if-null-then-new 部分周围放置一个 synchronized{} 块...我肯定更喜欢第二个选项。
  • 我认为(不幸的是)第一个解决方案是我的正确答案。主要是因为我无法在顶部初始化 staticField,所以必须在调用 initialize() 后对其进行初始化(我将编辑问题以反映这一点)。
  • 如果我们使用第一个代码块,我们必须使所有对 staticField 的访问在 SomeClass.class 周围同步。
  • 我通过使用 ClassName.staticField 更改了它的引用,但是 findbugs 仍然抱怨同样的事情。
【解决方案4】:

最好的办法是不做,尝试找到更好的设计模式。 如果真的有必要,这将起作用,并使 findbugs/spotbugs 不会抱怨。

public class Something
{
    private static SomeClass staticField = null;

    public Something()
    {
    }

    private void setStaticField(SomeClass value){
        staticField=value;
    } 

    public static SomeClass getStaticField()
    {
        if(staticField == null)
            setStaticField(new SomeClass());
        return staticField;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-17
    • 2011-02-13
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    • 2019-02-14
    相关资源
    最近更新 更多