DougW
DougW

Reputation: 30005

Eclipse equals() template where null String == empty String

Question
This question was originally to find out if anyone knows of a way to modify the Eclipse equals() and hashCode() templates to generate the following pattern for Strings (making null equivalent to "").

if ([value] == null || [value].length() == 0) {
    if (other.[value] != null && other.[value].length() > 0) {
        return false;
    }
} else if (![value].equals(other.[value])) {
    return false;
}

One suggested solution
A lot of answers have suggested normalizing input in the setters (either converting all empty strings to nulls, or nulls to empty strings). I find that dangerous. Here are two legitimate pieces of code that will crash the program if the user isn't aware of this side effect.

If all empty strings are made nulls, this will crash:

myObject.setName("");
String uppercaseName = myObject.getName().toUpperCase();

If all nulls are made empty strings, this will crash (debated advisability of this aside, I would generally expect it to work):

myObject.setName(myStringSubclassInstance);
MyStringSubclass string = myObject.getName().someCustomSubclassMethod();

If I went down this path, I would make the setters throw an InvalidArgumentException and spell that out in the documentation. That's the right way IMHO.

Better Solution
Ultimately, I don't think any of the recommended solutions were appropriate. This is not so much their fault, as it is the fault of the original question. After considering the feedback, I agree that the original question was predicated upon an inadvisable solution. I can't delete it though, so I've edited it to avoid misleading others.

What I decided to go with was utilizing the Builder Pattern to normalize values in the build() method. This results in objects that always have either null or empty Strings, but without adding side effects to setters or the equals() method.

Upvotes: 1

Views: 2285

Answers (3)

gpeche
gpeche

Reputation: 22504

Well if you do not care about null vs "", you could normalize the values inside of your class so they are always "". Then you would never be comparing nulls in your equals() method.

Upvotes: 0

Stephen C
Stephen C

Reputation: 718758

The trouble with your approach is null and empty Strings really are different values as far as the Java language is concerned, and even the String.equals() method treats null and an empty String as non-equal. So you need to replace all your String.equals comparisons for the fields with comparisons that deal with the null case.

This presents you with a bit of work, but your options include:

  • write your classes so that fields are never null,
  • write your own implementations of equals and hashCode for the classes, or
  • write your own wrapper class for the Strings.

The first is probably the best approach, especially if take it a step further and get rid of other code where null String values can creep in.

Upvotes: 1

Steve B.
Steve B.

Reputation: 57284

This might work for your application, but in general it's not really a good idea, especially for a template to apply globally. Null and "" are not the same thing in lots of cases - for example, if you consider these two as identical how can you distinguish between uninitialized and existing but empty values?

You might also consider initializing default values or using the apache EqualsBuilder

Upvotes: 3

Related Questions