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

belongs to group Basic

Identify possibly incorrect uses of == and equals()


This checker identifies incorrect or inefficient comparisons through equals() or ==. In some cases, these comparisons are wrong: for instance, strings should be compared for equality through == rather then through equals(). Classes can be safely compared through == instead. In other cases, these comparisons can be replaced by more efficient code.

Action: Check if the equality is actually wrong or can be replaced by more optimized code.

Examples


Consider the following program:

public class Main {
  public static boolean verbose;
  private final static String[] arr = new String[] { "verbose" };

  public static void main(String[] args) {
    if (args.length > 0)
      assert !args[0].equals("");

    if (args.length > 0 && args[0] == "verbose")
      verbose = true;

    if (args.equals(arr))
      verbose = true;

    if (args.length > 0) {
      Main m = new Main();
      System.out.println(m.test(args[0]));
      System.out.println(m.weAreRedefined());
    }
  }

  private boolean test(Object o) {
    return o == this;
  }

  public boolean weAreRedefined() {
    return !getClass().equals(Main.class);
  }
}

This checker issues the following warnings:

Main.java:7: [BadEq: InefficientStringEmptynessTest] Inefficient comparison with the empty string. Use isEmpty() instead
Main.java:9: [BadEq: EqualityWarning] Suspicious use of == rather than equals() to compare two java.lang.String
Main.java:12: [BadEq: EqualsOnArraysWarning] Suspicious call to equals() on arrays
Main.java:23: [BadEq: ImpossibleEqualityWarning] Always distinct objects are compared here
Main.java:27: [BadEq: EqualsWarning] Inefficient use of equals() rather than == to compare two java.lang.Class

Each of these warnings corresponds to incorrect or inefficient comparisons. In particular, == compares strings wrt identity, not wrt their content. The same happens for arrays, as at line 12, that should be compared element-wise. Moreover, at line 23, the comparison will always fail since objects of incompatible types are always compared there (a string and an instance of Main).

In this example, the programmer should rewrite the code as follows:

public class Main {
  public static boolean verbose;
  private final static String[] arr = new String[] { "verbose" };

  public static void main(String[] args) {
    if (args.length > 0)
      assert !args[0].isEmpty();

    if (args.length > 0 && args[0].equals("verbose"))
      verbose = true;

    if (java.util.Arrays.equals(args, arr))
      verbose = true;

    if (args.length > 0) {
      Main m = new Main();
      //System.out.println(m.test(args[0]));
      System.out.println(m.weAreRedefined());
    }
  }

  public boolean weAreRedefined() {
    return getClass() != Main.class;
  }
}