Java Forum / General / April 2007
equality and null pointers
julien.robinson2@gmail.com - 11 Apr 2007 16:13 GMT Hi all, a code factorization question...
the following expression: a.equals(b) returns a boolean, even if 'b' is null (in which case it's obviously false, because otherwise there would be a NullPointerException).
This is great for tests such as: "blob".equals(myPersonalString)
What if both a and b can be null? I end up writing the same code again and again... calling for factorization.
This is the factorized code:
public class Utils { public static boolean areEqual(Object obj1, Object obj2) { return (obj1 == null) ? (obj2 == null) : (obj1.equals(obj2)); } }
Questions are: - does this already exist somewhere in Java, and I have overlooked it (buried somewhere in with other utility methods)? - if not, does anybody prefer some other code than what I suggested?
This is nothing important, it's just annoying. I hate to rewrite code, and I don't like to define utilities that already exist, and it's such an insignificant problem... :-)
Thanks to all JR
visionset - 11 Apr 2007 16:45 GMT > Hi all, a code factorization question... > > the following expression: > a.equals(b) > returns a boolean, even if 'b' is null (in which case it's obviously > false, because otherwise there would be a NullPointerException). Well here lies your problem. Personally I'd say it was more likely that null != null Just like in SQL.
So this underlines the fact that only you, your design in your application can determine what equality is. For the same reason you override equals() to put your spin on equality so you must determine if null == null, nul!=null or indeed what myObj.equals(null) should evaluate to.
> This is great for tests such as: > "blob".equals(myPersonalString) [quoted text clipped - 14 lines] > (buried somewhere in with other utility methods)? > - if not, does anybody prefer some other code than what I suggested?
 Signature Mike W
CodeForTea@gmail.com - 11 Apr 2007 17:37 GMT > <julien.robins...@gmail.com> wrote in message > [quoted text clipped - 41 lines] > > - Show quoted text - Here is some code showing equals and hascode that you can implement in your calsses.
public class Worker { private String name; private double salaryRate;
public Worker (String name, double rate) { this.name = name; this.salaryRate = rate; }
public int hashCode() { final int PRIME = 31; int result = 1; result = PRIME * result + ((name == null) ? 0 : name.hashCode()); long temp; temp = Double.doubleToLongBits(salaryRate); result = PRIME * result + (int) (temp ^ (temp >>> 32)); return result; }
public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final Worker other = (Worker) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (Double.doubleToLongBits(salaryRate) != Double.doubleToLongBits(other.salaryRate)) return false; return true; } }
Dinesh
julien.robinson2@gmail.com - 12 Apr 2007 13:05 GMT in fact, you provide an example of use of what I was talking about...
On Apr 11, 6:37 pm, CodeFor...@gmail.com wrote:
> Here is some code showing equals and hascode that you can implement in > your calsses. [snip]
> if (name == null) { > if (other.name != null) > return false; > } else if (!name.equals(other.name)) > return false; This piece of code is more or less equivalent to calling my "areEqual(name, other.name)" (except that I prefer my version, sorry).
So basically, you're answering my need for factorization with "don't factorize, write it". :-)
Thanks all the same JR
CodeForTea@gmail.com - 13 Apr 2007 12:22 GMT On Apr 12, 8:05 am, julien.robins...@gmail.com wrote:
> in fact, you provide an example of use of what I was talking about... > [quoted text clipped - 17 lines] > Thanks all the same > JR public class Utils { public static boolean areEqual(Object obj1, Object obj2) { return (obj1 == null) ? (obj2 == null) : (obj1.equals(obj2)); }
} I fail to see how this helps. Why do you need two methods to compare an object when one will do? You call the equals method in your areEqual method.
Dinesh
julien.robinson2@gmail.com - 16 Apr 2007 08:19 GMT On Apr 13, 1:22 pm, CodeFor...@gmail.com wrote:
> I fail to see how this helps. Why do you need two methods to compare > an object when one will do? You call the equals method in your > areEqual method. > > Dinesh Hi, I feel like we're talking at right angles here. :-)
Let me try to explain... I was asking about code factorization. It's a piece of code that I write very often*, and it's (very) good practice in that case to factorize, i.e. write it only once and then call it.
You answered me with some equals() code. 1. the "equals" method itself does not address my problem, because I was speaking about 2 pointers that may both be null... and you can't call "equals" on a null pointer 2. inside your "equals" method was a part (that I quoted) that looked like what I was doing, so I assumed that was what you were talking about, and answered that.
Hope this clears it up. If not, it's just a slight miscomprehension, no great deal. :-)
The answer to your last question is: . I use the "equals" method, only one method, when I'm sure I have a non-null pointer to call it on . the other method is for pointers that I'm not sure are null or not . I call "areEqual" in "equals" because that's factorization (avoiding to write the same code again and again).
JR * this was before recounting the votes of course :-)
Lew - 12 Apr 2007 02:26 GMT > Well here lies your problem. > Personally I'd say it was more likely that > null != null > Just like in SQL. There is no "likely" in Java. There is what it is, and there isn't what it ain't. One thing it ain't is probabilistic.
Why in the world should anything in Java be "just like in SQL"? Java is nothing like SQL.
(null == null) is true, just for your reference.
> So this underlines the fact that only you, your design in your application > can determine what equality is. > For the same reason you override equals() to put your spin on equality so > you must determine if null == null, nul!=null or indeed what > myObj.equals(null) should evaluate to. Come on, already! I'm sorry, but I have absolutely no idea where you came up with this. I am very interested in how people learn Java. From where did you learn this poppycock?
== is precisely defined and set by the rules of the Java language. What are you, Humpty Dumpty?
> 'When _I_ use a word,' Humpty Dumpty said in rather a scornful tone, > 'it means just what I choose it to mean--neither more nor less.' - /Through the Looking Glass/, Lewis Carroll
It is totally not up to the OP, you or me what == means. And there is no mechanism in Java to "put your spin on" it, either.
To the OP:
You should be range-checking values anyway. It is not redundant to check for both null and the empty string; they are different values.
It's not so bad to write a utility method like the one you showed if you commonly treat both null and "" as equivalently undesirable. However, the language itself treats the cases differently because they are.
 Signature Lew
visionset - 12 Apr 2007 09:43 GMT >> Well here lies your problem. >> Personally I'd say it was more likely that [quoted text clipped - 8 lines] > > (null == null) is true, just for your reference. No sh.t sherlock.
>> So this underlines the fact that only you, your design in your >> application can determine what equality is. [quoted text clipped - 15 lines] > It is totally not up to the OP, you or me what == means. And there is no > mechanism in Java to "put your spin on" it, either. I'd have thought it was quite obvious that I'm talking about the Java languages definitions. That is so simple, I'd not even reply with that information. I'm obviously talking about what null means and how it relates to other values **for your business logic** Pehaps I shouldn't have used the same syntax. But like I said I thought it was obvious. It obviously was to most, otherwise I wouldn't escaped such abuse for so long...
> To the OP: > [quoted text clipped - 3 lines] > It's not so bad to write a utility method like the one you showed if you > commonly treat both null and "" as equivalently undesirable. 'if you treat' ie your applications business logic is such that...
> However, the language itself treats the cases differently because they > are.
 Signature Mike W
Lew - 12 Apr 2007 13:07 GMT > I'd have thought it was quite obvious that I'm talking about the Java > languages definitions. [quoted text clipped - 3 lines] > Pehaps I shouldn't have used the same syntax. But like I said I thought it > was obvious. I am sorry that I misunderstood what you were saying. Could you explain it?
When you say it's up to the programmer
>> For the same reason you override equals() to put your spin on equality so >>> you must determine if null == null, nul!=null How can you decide that null != null? The language says that null == null.
 Signature Lew
visionset - 12 Apr 2007 13:30 GMT >> I'd have thought it was quite obvious that I'm talking about the Java >> languages definitions. [quoted text clipped - 14 lines] > How can you decide that null != null? The language says that null == > null. Like I said for the purposes of your problem space. I did not actually mean:
if (null != null) System.out.println("look, I've just proved the JLS wrong");
I meant that if two of your domain objects of type Foo are null then they are probably not 'equal' where equality is something defined by your domain logic. But then they could be, this is where 'you decide' means applicability to you domain.
Boy do I regret lazily using syntax that could be confused with Java source. But then it's shared by the majority of languages these days.
 Signature Mike W
Wojtek - 12 Apr 2007 15:12 GMT visionset wrote :
> I meant that if two of your domain objects of type Foo are null then they are > probably not 'equal' where equality is something defined by your domain > logic. But then they could be, this is where 'you decide' means applicability > to you domain. An object will never be null. It either exists or it does not.
A reference, on the other hand, can refer to an object (not null) or can refer to null (is null).
 Signature Wojtek :-)
visionset - 12 Apr 2007 15:15 GMT > visionset wrote : >> [quoted text clipped - 7 lines] > A reference, on the other hand, can refer to an object (not null) or can > refer to null (is null). Yes sloppy terminology, I do appologise!
 Signature Mike W
Stefan Ram - 12 Apr 2007 15:18 GMT >An object will never be null. It either exists or it does not. ¯¯¯¯¯¯¯¯ An object that does not exist is not an object at all. Therefore, an object always exists.
(The phrase »not exists« actually makes sense in the context of object descriptions P: When there is no object so that P(o) is true, one says informally »io:P(o) does not exist.«, i.e., »The object o, so that P(o), does not exists.«. This does not mean, however, that there are objects that do not exists. Those objects would exist and not exist.)
Wojtek - 12 Apr 2007 15:33 GMT Stefan Ram wrote :
>> An object will never be null. It either exists or it does not. > ¯¯¯¯¯¯¯¯ [quoted text clipped - 8 lines] > however, that there are objects that do not exists. > Those objects would exist and not exist.) Between my phrase "It either exists or it does not" and your phrase "Those objects would exist and not exist" there is not a lot of difference.....
My point was that it is not an object which is null, but rather a reference which can refer to a null.
 Signature Wojtek :-)
visionset - 12 Apr 2007 15:36 GMT >> however, that there are objects that do not exists. >> Those objects would exist and not exist.) [quoted text clipped - 4 lines] > My point was that it is not an object which is null, but rather a > reference which can refer to a null. He was upping the pedantry to def con one, one more than you ;-/
 Signature Mike W
Larry Barowski - 12 Apr 2007 16:03 GMT > I meant that if two of your domain objects of type Foo are null then they > are probably not 'equal' where equality is something defined by your > domain logic. But then they could be, this is where 'you decide' means > applicability to you domain. And at the primitive level, you may sometimes want NaN to be equal to NaN, although they will compare as not equal. For example, double x = Math.sqrt(-2); System.out.println((x == x)); prints "false".
Lew - 13 Apr 2007 02:41 GMT > And at the primitive level, you may sometimes want NaN to be > equal to NaN, although they will compare as not equal. For example, > double x = Math.sqrt(-2); > System.out.println((x == x)); > prints "false". Why would one want NaN to equal NaN? Doesn't that violate the fundamental meaning of NaN?
 Signature Lew
Jaakko Kangasharju - 13 Apr 2007 07:26 GMT > Why would one want NaN to equal NaN? Doesn't that violate the > fundamental meaning of NaN? Apparently, at least when you want to use Doubles as hash table keys. See <http://java.sun.com/javase/6/docs/api/java/lang/Double.html#equals(java.lang.Object)>.
It also makes sense when you're, say, writing data marshaling and unmarshaling code and need to test it.
 Signature Jaakko Kangasharju, Helsinki Institute for Information Technology Want a Gmail account? Just email me.
Larry Barowski - 13 Apr 2007 15:22 GMT >> And at the primitive level, you may sometimes want NaN to be >> equal to NaN, although they will compare as not equal. For example, [quoted text clipped - 4 lines] > Why would one want NaN to equal NaN? Doesn't that violate the fundamental > meaning of NaN? The last time I ran into it was indirectly. I was developing a Java debugger that highlights fields when their values change. Naively using com.sun.jdi.DoubleValue.equals() for comparison of old and new values resulted in float and double NaN values that were always highlighted after their first appearance.
Also, in addition to what Jaakko pointed out, you may want them to be considered equal for sorting purposes (where you also need to use a different < or > comparison to compare NaN to non-NaN).
In any case where floating point numbers can be NaN, you need to watch out for:
if(x > y) ... else if(x < y) ... else // Wrongly assume x == y in all cases here.
Lew - 13 Apr 2007 16:51 GMT > The last time I ran into it was indirectly. I was developing a > Java debugger that highlights fields when their values > change. Naively using com.sun.jdi.DoubleValue.equals() > for comparison of old and new values resulted in float > and double NaN values that were always highlighted after > their first appearance. As you say, "naively" using. The fault, dear Caesar, lies not in our NaNs, but in ourselves.
> Also, in addition to what Jaakko pointed out, you may want > them to be considered equal for sorting purposes You may want them to be, but they aren't.
> (where you also need to use a different < or > comparison to > compare NaN to non-NaN).
> In any case where floating point numbers can be NaN, > you need to watch out for: [quoted text clipped - 5 lines] > else > // Wrongly assume x == y in all cases here. That error is the programmer's. The programmer should not wrongly assume x == y in all cases, as you point out.
The very definition of NaN is that it is not comparable to any number, and that it is not equal to any number.
> a numeric comparison operation involving one or two NaNs returns false and any != comparison involving NaN returns true, including x!=x when x is NaN. Its purpose is to represent the value of "an operation that has no mathematically definite result". If it's not mathematically definite, it can't be compared and it can't be equal.
So the right way to code it would be
if ( x > y ) { ... } else if ( x < y ) { ... } else if ( x == y ) { ... } else { ... }
 Signature Lew
visionset - 13 Apr 2007 17:47 GMT >> Also, in addition to what Jaakko pointed out, you may want >> them to be considered equal for sorting purposes [quoted text clipped - 7 lines] > mathematically definite result". If it's not mathematically definite, it > can't be compared and it can't be equal. Lew you certainly are a Programmer.
 Signature Mike W
Larry Barowski - 13 Apr 2007 21:49 GMT >> Also, in addition to what Jaakko pointed out, you may want >> them to be considered equal for sorting purposes > > You may want them to be, but they aren't. I think you are responding to something I have not written. They are considered equal for sorting purposes, by java.lang.Double for example.
> That error is the programmer's. The programmer should not wrongly assume > x == y in all cases, as you point out. I never implied otherwise. I was not arguing that primitive NaNs should compare as equal by the == operator, as you seem to be assuming. I didn't think I gave that impression, but perhaps I was not 100% clear.
Lew - 14 Apr 2007 00:59 GMT > I never implied otherwise. I was not arguing that primitive NaNs > should compare as equal by the == operator, as you seem to be > assuming. I didn't think I gave that impression, but perhaps I was > not 100% clear. More likely I wasn't 100% listening.
If I understand you correctly, you want for certain purposes like sorting to put all NaNs in the same bucket.
You could write a Comparator for Doubles that treats NaN the way you want, then use <http://java.sun.com/javase/6/docs/api/java/util/Collections.html#sort(java.util. List,%20java.util.Comparator)>
 Signature Lew
julien.robinson2@gmail.com - 12 Apr 2007 13:35 GMT > There is no "likely" in Java. There is what it is, and there isn't what it > ain't. One thing it ain't is probabilistic. Thanks. :-)
[To visionset:]
>From what I understand, you're in fact saying, *not* that (null != null), but that it's probably not a good idea to use that test in code, because null is a special value and should be treated as such. Is that what you're saying? I see your point, even if I don't think it's a generalizable good practice rule. For me, null values should generally be documented, and that's where my personal rules stop. They may be meaningful, and their comparison too, in many cases.
[back to Lew]
> To the OP: Hi! :-)
> You should be range-checking values anyway. It is not redundant to check for > both null and the empty string; they are different values. If I may say so, you are answering a special case of my question. The string stuff was an example. In fact, you're more or less saying the same as visionset: treat the null values as special values, don't compare them! I agree in some cases (I'm not speaking of those here), not in all cases.
> It's not so bad to write a utility method like the one you showed if you > commonly treat both null and "" as equivalently undesirable. However, the > language itself treats the cases differently because they are. I'm not blaming the language! Of course it treats them differently... in fact, it doesn't treat null at all in this case, because "null.equals(null)" simply throws a null pointer exception (as well it should). :-)
Here's an example of what I'm saying:
public class MyStuff { private A a; private B b; /* ...many others... */
@Override public boolean equals(Object obj) { if (obj == null) { return false; } if (obj == this) { return true; } if (! (obj instanceof EntityAction)) { return false; } MyStuff otherStuff = (MyStuff) obj; return Utils.areEqual(a, otherStuff.a) & Utils.areEqual(b, otherStuff.b); // ..and all the other stuff } }
If I wasn't using my utility method, I would simply be copy-pasting code all around (which is what <CodeFor...@gmail.com> suggested). And of course, sometimes null values are special, but in the "equals()" method, I simply want to compare two instances. Let's say it's for the sake of a collections utility method, searching, sorting etc. I don't want any checking logic in there, because if there is any null value management, it should be in the constructor, the setter, the deserializer or someplace like that. It's not up to the "equals()" method to refuse / accept null values. If I may add, if business logic implies that "a" cannot be null, the code could simply be...
return a.equals(otherStuff.a) & Utils.areEqual(b, otherStuff.b); // ..and all the other stuff
I still think I need this method. I'm sure many people need it, and among those who don't, a lot surely simply forget a couple of defensive tests or don't mind about code copying (I've come across both)... which is not *extremely* bad, as I said before it's a minor point, I've seen worse. :-) My questions, open as they were, were more about how to best do it and does it exist... Apparently it doesn't exist in Java utilities. Too bad. This being said, thanks for the answers! JR
Chris Uppal - 12 Apr 2007 13:54 GMT > public class Utils { > public static boolean areEqual(Object obj1, Object obj2) { > return (obj1 == null) ? (obj2 == null) : (obj1.equals(obj2)); > } > } Just as a side comment. It's pretty unusual to use null as an explicit value -- say (just for the sake of argument) that 1 in 100 methods allow null parameters of some sort. So the number of methods which will expect/allow null in /two/ parameters will be correspondingly smaller (1 in 10000 in this example). I doubt whether it is worth creating utility methods to help with cases that crop up so rarely.
Put it another way: if you are passing around so many nulls, then you may be overusing nulls-as-values in your designs.
-- chris
julien.robinson2@gmail.com - 12 Apr 2007 17:08 GMT On Apr 12, 2:54 pm, "Chris Uppal" <chris.up...@metagnostic.REMOVE- THIS.org> wrote:
> Put it another way: if you are passing around so many nulls, then you may be > overusing nulls-as-values in your designs. This got me thinking about frequency, not methods. So I quizzed my source. I've just written the utility, so I didn't know yet how many times it would prove useful in my current project.
These are the statistics (please restrain from laughing out loud :-) ) . 262 classes . 3 classes where it's useful.
2 of these are the equals() method. The other is a collection manipulation (so it's more or less equals()).
All around, in fact, null values are specifically managed, and often forbidden from the start. Ergo, the code already follows the advice of you all (well, 259 times out of 262!). :-)
Which could mean that in this discussion everyone was right. :-) * Yes, beware of null pointers and manage them separately. * But yes, it's sometimes useful to use my code (and since no one has suggested better, I'll keep it as a static utility method in a separate class).
So there you go. Still, I was happy to see what other coders thought about this... JR
Chris Uppal - 13 Apr 2007 09:30 GMT > These are the statistics (please restrain from laughing out loud :-) ) > . 262 classes > . 3 classes where it's useful. Thanks for the follow-up. It's always interesting to see real numbers in questions like this.
-- chris
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|