Checker StaticFieldAccess   as of Julia version 2.6.0 (built on 6 Sep 2018)

belongs to group Basic

Identify where a static field is modified in a non-static context


Static fields can be updated from a static context, but this is a bad programming practice:

  • it might introduce bugs due to unsafe synchronization between concurrent threads that try to modify the same static field
  • it makes impossible to instantiate a class more than once, since static fields would be (incorrectly) shared by all instances.

    In object-oriented code, fields should mostly be instance fields; static fields should be used in rare situations, such as for constants. This checker looks for static fields that are assigned from non-static contexts. It only considers as acceptable assignments that are used for the lazy initialization of static fields, although they might occur in non-static contexts. That is current programming practice.

    Action: Check if static fields can be replaced by instance fields or if methods can be made static.

    Examples


    Consider the following program:

    public class Scores {
      private static int[] scores = new int[100];
      private static int next;
    
      public static void main(String[] args) {
        new Scores();
      }
    
      public void addScore(int score) {
        if (next < scores.length)
          scores[next++] = score;
      }
    
      public float average() {
        float sum = 0.0f;
        for (int pos = 0; pos < next; pos++)
          sum += scores[pos];
    
        return sum / next;
      }
    }
    

    This checker issues the following warnings:

    Scores.java:11: [StaticFieldAccess: SetStaticInNonStaticWarning] Modification of static field next from a non-static context
    Scores.java:11: [StaticFieldAccess: SetStaticInNonStaticWarning] Modification of static field scores from a non-static context

    These warnings are sensible since class Scores can be instantiated only once: all its instances share the same array of scores, which would be incorrect.

    In this example, and in better object-oriented style, the programmer should replace the static fields with instance fields:

      private int[] scores = new int[100];
      private int next;
    

    Consider now the following program, that lazily initializes two static fields:

    public class LazyInitialisation {
      private static Map session;
      private static Map session2;
    
      public @EntryPoint Map getSession() {
        if (session == null) {
          System.out.println("Initializing session");
          // this is acceptable, since it is a lazy initialization idiom
          session = new HashMap<>();
        }
    
        return session;
      }
    
      public @EntryPoint Map getSession2() {
        if (session == null) {
          System.out.println("Initializing session2");
          // this is not acceptable, since it is not a lazy initialization idiom
          session2 = new HashMap<>();
        }
    
        return session2;
      }
    }
    

    This checker issues the following warning:

    LazyInitialisation.java:19: [StaticFieldAccess: SetStaticInNonStaticWarning] Modification of static field session2 from a non-static context

    since the initialization of static field session2 occurs in a non-static context and is not part of the lazy initialization idiom. Instead, no warning is issued for the assignment to static field session at line 9.

    In this example, the programmer has probably coded the lazy initialization of field session2 incorrectly and should check for nullness of session2 at line 16.