equality and null pointers

J

julien.robinson2

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
 
V

visionset

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.
 
C

CodeForTea

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.

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
 
L

Lew

visionset said:
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.
 
V

visionset

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.

No shit sherlock.
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?

- /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.

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:

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.

'if you treat'
ie
your applications business logic is such that...
 
J

julien.robinson2

in fact, you provide an example of use of what I was talking about...

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
 
L

Lew

visionset said:
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.

I am sorry that I misunderstood what you were saying. Could you explain it?

When you say it's up to the programmer
How can you decide that null != null? The language says that null == null.
 
V

visionset

Lew said:
I am sorry that I misunderstood what you were saying. Could you explain
it?

When you say it's up to the programmer

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.
 
J

julien.robinson2

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 <[email protected]> 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
 
C

Chris Uppal

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
 
W

Wojtek

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).
 
V

visionset

Wojtek said:
visionset wrote :

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).

Yes sloppy terminology, I do appologise!
 
S

Stefan Ram

Wojtek said:
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.)
 
W

Wojtek

Stefan Ram wrote :
¯¯¯¯¯¯¯¯
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.)

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.
 
V

visionset

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.

He was upping the pedantry to def con one, one more than you ;-/
 
L

Larry Barowski

visionset said:
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".
 
J

julien.robinson2

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
 
L

Lew

Larry said:
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?
 
C

Chris Uppal

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,231
Members
46,820
Latest member
GilbertoA5

Latest Threads

Top