Mostly technical stuff with some interesting moments of life

Java Strings: literal.equals(param) OR param.equals(literal)

6 comments
Comparing strings is bit tricky :) Say for an example you want to test a String reference against the literal "hello". In simple terms you have a String (say helloStr) and you want to see if the content of that is equals to "hello". You have two choices here,

1. helloStr.equals("hello")

2. "hello".equals(helloStr)

Both will do fine, but which is the better one? I've been using the second form but never thought of the difference (hmm, that's bad ;) anyway people do remember certain things bit later). In one of the code reviews at WSO2 it was revealed. The first form can lead to a Null pointer exception in the case when the helloStr is null. The second option will save you from this since the literal "hello" is not null always and you are invoking a method of a not null object. In this case even if the helloStr is actually null it doesn't matter because it'll only cause the program to check "hello" against null which results false.

If you are checking two String references then you have no option, but always try to invoke the equals() from the most probably not null reference.

Little things do matter :)

6 comments :

  1. Typo, should be:

    "hello".equals(helloStr)

    Not:

    "hello".equals("helloStr")

    ... which is always false :-)

    ReplyDelete
  2. Thanks for the correction. I changed it :)

    ReplyDelete
  3. I think, if you are checking equality of two references, then you may follow this--

    if(ref1 != null && ref2 != null) {
    ref1.equals(ref2);
    }

    it will avoid the NullPointerException.

    ReplyDelete
  4. @jtanzy: nice! actually you will need to check only one variable.

    if (ref1 != null) {
    ref1.equals(ref2);
    }

    ReplyDelete
  5. So, basically, instead of detecting a potential bug in your code via a clean immediate null pointer exception, you covered the bug by returning false on the literal vs. object comparison. Consequently, your null string causes your program to blow up at a later stage when it is potentially much harder to detect the bug.

    I disagree with the conclusion that literal.equals(object) is better than object.equals(literal). I would rather detect the exception and fix the bug than silently let it slide by.

    ...unless you actually know, in advance, by design, for absolute certain, that is is acceptable for the object to be null, but that strikes me as likely to be the exception in most situations, not the rule. In other words, the default usage should be object.equals(literal) except when you are absolutely certain, by design, that a given situation could provide a perfectly legal and valid null object.

    ReplyDelete
    Replies
    1. You seems to have missed the point here and have thought the entire program as one piece. The essence here is should the piece of code doing the check needs to know about proper values for variables. In its (code doing the check) view, it's being asked to check an object against a literal for equality and it should do exactly that. A null check or any other restriction on the values that can be checked for equality should have been properly handled beforehand, but doing literal.equal(object)will give essentially the correct semantics to the check, i.e. return false, even when such restrictions are not handled properly. If the program fails because of a null value it should not be blamed on the equal check.

      Delete