noob question: string comparing

U

user

if i want to compare a string str to something like... the letter f,
what do i do?
(str == "f") seems to return false everytime.
 
L

Lars Enderin

user skrev:
if i want to compare a string str to something like... the letter f,
what do i do?
(str == "f") seems to return false everytime.
The == operator compares String pointers, not values. Use
"f".equals(str). The comparison order avoids null references.
 
T

Tim Ward

Lars Enderin said:
user skrev:
The == operator compares String pointers, not values. Use
"f".equals(str). The comparison order avoids null references.

And ... for an encore ... the "byte" data type is signed!!

(There are a number of completely mad design decisions in the Java language
but these two have got to be the worst ... unless anyone can come up with
any even more ludicrous examples? There's constructors calling virtual
methods on partially-constructed objects, of course, but that one tends to
bite people later on.)
 
E

Eric Sosman

Tim said:
And ... for an encore ... the "byte" data type is signed!!

(There are a number of completely mad design decisions in the Java language
but these two have got to be the worst ...

The signedness of `byte' is unfortunate, and is possibly
a product of the hobgoblin of little minds. But keeping the
notions of `==' and `.equals()' separate is another matter; if
you consider it "mad" I suspect you haven't thought about it
enough. ("People go mad if they think too much.")
 
D

David Segall

user said:
if i want to compare a string str to something like... the letter f,
what do i do?
(str == "f") seems to return false everytime.
I have found it a very difficult lesson to learn but == in Java does
not have the same meaning as equals in other languages. If you want to
test for equality you need to use the equals method of the object str
so you need to test as follows:
if (str.equals"f") {...
or, God forbid,
if ("f".equals(str)) {...

It seems that origin of this is that it is much easier, when writing
an interpreter that is meant to work in a tiny "set top box" computer,
to test for equality between two pointers to an object than to test if
a human interpretation of the two objects are equal. Consequently,
unless the arguments are primitive types, == just checks to see if the
two arguments are the same object.
 
E

Eric Sosman

David Segall wrote On 07/31/06 10:36,:
I have found it a very difficult lesson to learn but == in Java does
not have the same meaning as equals in other languages. If you want to
test for equality you need to use the equals method of the object str
so you need to test as follows:
if (str.equals"f") {...
or, God forbid,
if ("f".equals(str)) {...

It seems that origin of this is that it is much easier, when writing
an interpreter that is meant to work in a tiny "set top box" computer,
to test for equality between two pointers to an object than to test if
a human interpretation of the two objects are equal. Consequently,
unless the arguments are primitive types, == just checks to see if the
two arguments are the same object.

It's not a matter of easier or harder, but of modelling
the real world satisfactorily. The real world presents us
with multiple different notions of "equality," two of which
are supported by Java:

- Identity: Two objects A and B are "equal" if they are
in fact the same object under different names. "David"
and "Mr. Segall" refer to the same object (granting a
suitable universe of discourse), so they are equal.
This is the "equality" Java's == operator tests.

- Equivalence: Two objects A and B are "equal" if they
are of the same class and have the same "value." This
bottle of Pirelli's Miracle Elixir contains 100 ml. of
that efficacious fluid, that other bottle holds the
same amount of the same stuff, so the two bottles are
"equal" in the sense of being equivalent. This is the
notion the equals() method tests (depending, of course,
on how the class defines the method).

If you are having trouble separating these two notions,
consider your wallet for a moment. By pure coincidence, it
happens to contain the same amount of money as my wallet.
The two wallets are therefore equal in purchasing power; does
that mean they are the same wallet? If so, hand over your
wallet immediately: it's mine!
 
D

David Segall

Eric Sosman said:
David Segall wrote On 07/31/06 10:36,:

It's not a matter of easier or harder, but of modelling
the real world satisfactorily. The real world presents us
with multiple different notions of "equality," two of which
are supported by Java:

- Identity: Two objects A and B are "equal" if they are
in fact the same object under different names. "David"
and "Mr. Segall" refer to the same object (granting a
suitable universe of discourse), so they are equal.
This is the "equality" Java's == operator tests.

- Equivalence: Two objects A and B are "equal" if they
are of the same class and have the same "value." This
bottle of Pirelli's Miracle Elixir contains 100 ml. of
that efficacious fluid, that other bottle holds the
same amount of the same stuff, so the two bottles are
"equal" in the sense of being equivalent. This is the
notion the equals() method tests (depending, of course,
on how the class defines the method).

If you are having trouble separating these two notions,
consider your wallet for a moment. By pure coincidence, it
happens to contain the same amount of money as my wallet.
The two wallets are therefore equal in purchasing power; does
that mean they are the same wallet? If so, hand over your
wallet immediately: it's mine!
I don't dispute your two concepts of equality but you have used
sleight of hand to claim my wallet. I have no objection to being
forced to explicitly compare wallet.colour, wallet.size etc in
addition to wallet.value to protect my wallet. Java confuses beginners
because it assigns a default property (.value) to a String object in
the equals() method but omits that property and insists on using the
unfamiliar concept of "identity" with the == operator. This contrasts
with most (all?) other languages which is why I concluded that it was
done for the benefit of the interpreter programmer rather than the
application programmer.
 
O

Oliver Wong

David Segall said:
I don't dispute your two concepts of equality but you have used
sleight of hand to claim my wallet. I have no objection to being
forced to explicitly compare wallet.colour, wallet.size etc in
addition to wallet.value to protect my wallet.

I don't think the wallet is the greatest example, but you could imagine
that your wallet and Eric's wallet are identical in every respect (colour,
number of protons, electrons and neutrons that compose it, etc.), but the
two wallets are still distinct.

Maybe this example will be better:

Alice and Bob are speaking:

Alice: "I'm thinking of a specific friend."
Bob: "I too am thinking of a specific friend."
Alice: "My friend is 28 years old."
Bob: "My friend is also 28 years old."
Alice: "My friend has brown eyes, blond hair."
Bob: "Mine too."
Alice: "My friend's name is Charlie."
Bob: "So is mine!"
[etc. This goes on, Alice listing a whole bunch of attributes about her
friend, and Bob saying those same attributes apply to his friend.]

So, are Alice and Bob thinking about the same person? It might be, or it
might not be. It's possible that they are speaking about two completely
different people who are remarkably similar, or it might be that they are in
fact speaking about the exact same person, not knowing that they had a
common friend.

Alice: "Well, my friend Charlie's cell phone number is 12345678901."
Bob: "Oh, well I don't know what my Charlie's cell phone number is. However,
his house number is 19876543210."
Alice: "Hmm, I don't know what my friend's Charlie's home number is."

Just like a person can have multiple phone numbers, so can objects in
Java have multiple references pointing to them. The fact that you have two
different references doesn't nescessarily mean you have two different
objects!

Alice: "Well, my friend Charlie lives alone at 22 Baker Street."
Bob: "Ah, so does mine. So we must be talking about the same person."

One way to think of it is that references are sort of like pointers
which hold the address of the objects they are refering to. When you use the
== operator on two reference, it's comparing the addresses that each
reference points to, to see if they are identical. When you invoke the
..equals() method, you're invoking it on a specific object, and that method
is free to do anything the programmer designed it to do. In fact, it can
even "lie" to you and return false when you check if an object is equal to
itself, or it can be programmed to erase all the files on your haddrive,
etc.

Usually, you assume that the programmer who wrote the equals is not
malicious, and you can just read the documentation for the equals() method
to find out exactly how it determines equality between two objects, or
failing that, read the source code itself.
Java confuses beginners
because it assigns a default property (.value) to a String object in
the equals() method but omits that property and insists on using the
unfamiliar concept of "identity" with the == operator.

I think this "assigning a default property (.value) to a String object"
explanation may be very misleading. The JVM never creates fields out of
nowhere. If a object has a field, it's because the class that defines that
object declared the field. If you look at the source code for the String
class, it actually has 4 fields:

private final char value[];
private final int offset;
private final int count;
private int hash;

If you check the source code for the equals() method in String, you'll see
it essentially does a character-by-character scan from value[offset] to
value[offset + count - 1] to check if two string objects are equal. So it's
possible that two String object have completely different field values, but
are evaluated to be equal! For example if the two String's field values are:

StringOne {
value[] = {'A', 'B', 'C', '1', '2', '3'}
offset = 3;
count = 3;
hash = 42;
}

and

StringTwo {
value[] {'1', '2', '3', 'X', 'Y', 'Z'}
offset = 0;
count = 3;
hash = 69;
}

StringOne.equals(StringTwo) would return true, because of the way it's
programmed.
This contrasts
with most (all?) other languages which is why I concluded that it was
done for the benefit of the interpreter programmer rather than the
application programmer.

I think what you were missing was the fact that the .equals() method can
be programmed to do anything the programmer wishes.

- Oliver
 
D

dsjoblom

David said:
It seems that origin of this is that it is much easier, when writing
an interpreter that is meant to work in a tiny "set top box" computer,
to test for equality between two pointers to an object than to test if
a human interpretation of the two objects are equal. Consequently,
unless the arguments are primitive types, == just checks to see if the
two arguments are the same object.

Which also happens to be the case with pointers in C. And since java
borrows heavily on syntax (and some semantics) from C, and java
references are essentially pointers, the function of == is not that
surprising, and has nothing to do with ease of implementation. I might
also add that if the == operator didn't do what it currently does, we
would need some other way of checking reference equality.

Regards,
Daniel Sjöblom
 
E

Eric Sosman

David Segall wrote On 07/31/06 12:20,:
[...]
I don't dispute your two concepts of equality but you have used
sleight of hand to claim my wallet.

Sleight of hand, prestidigitation, trickery and ruses,
scams and frauds -- if I can grab other peoples' wallets,
it's all worth while! ;-)
I have no objection to being
forced to explicitly compare wallet.colour, wallet.size etc in
addition to wallet.value to protect my wallet. Java confuses beginners
because it assigns a default property (.value) to a String object in
the equals() method but omits that property and insists on using the
unfamiliar concept of "identity" with the == operator.

I'm not at all sure what you mean by a "default" property.
The String.equals() method makes a computation, just as other
equals() methods -- other anything() methods -- make their
computations. String.equals() takes one set of things into
account; BigInteger.equals() computes things differently;
neither seems (to me) to "default" to anything.
This contrasts
with most (all?) other languages

Here I must disagree, although it's risky: I've used only
a couple dozen programming languages, well short of "most."
But among those I've used that support the notion of "reference"
as a first-class value, I cannot think of any that make Java
seem at all unusual in this regard. All of them made a clear
distinction between the reference and the thing referred to.

In C, consider

char *p = "Hello, world!";
char *q = malloc(strlen(p) + 1); /* assume success */
strcpy (q, p);

This fragment points p at a character string, then points q
at an exact copy of that string. At this point p and q are
not == because they point to different string instances, yet
strcmp(p, q) reports that the strings compare equal. This
should seem eerily similar to Java's behavior with

String p = "Hello, world!";
String q = new String(p);

And if you find two notions of "equality" confusing, it's
a good thing you never encountered Lisp! My Lisp days are far
behind me and my memory of them has gone a bit foggy, but I
recall that Common Lisp supports at least four different notions
of equality, maybe five.
which is why I concluded that it was
done for the benefit of the interpreter programmer rather than the
application programmer.

I don't think the conclusion follows from the premise.
 
I

Ian Wilson

Eric said:
The signedness of `byte' is unfortunate, and is possibly
a product of the hobgoblin of little minds. But keeping the
notions of `==' and `.equals()' separate is another matter; if
you consider it "mad" I suspect you haven't thought about it
enough. ("People go mad if they think too much.")

Keeping the notions of "equal value" and "refer to same object" separate
is good. But I sometimes wonder if the operators could have been
allocated in such a way as to cause least confusion to learners.

e.g. == for the extremely commonly meant 'has same string value as' and
..sameObject() for the far less used 'are both references to the same thing'.
 
E

Eric Sosman

Ian Wilson wrote On 08/15/06 04:55,:
Keeping the notions of "equal value" and "refer to same object" separate
is good. But I sometimes wonder if the operators could have been
allocated in such a way as to cause least confusion to learners.

e.g. == for the extremely commonly meant 'has same string value as' and
.sameObject() for the far less used 'are both references to the same thing'.

How would you test for a null reference in this scheme?

someString.equals(null) // NPE if someString is null
null.equals(someString) // doesn't compile
((String)null).equals(someString) // NPE always

I guess the test *could* be made:

static boolean isReferenceNull(Object ref) {
try {
ref.getClass(); // NPE if ref is null
return false; // no NPE -> not null
}
catch (NullPointerException ex) {
return true; // only one way to get here
}
}

.... but this is vile.
 
O

Oliver Wong

Eric Sosman said:
Ian Wilson wrote On 08/15/06 04:55,:

How would you test for a null reference in this scheme?

someString.equals(null) // NPE if someString is null
null.equals(someString) // doesn't compile
((String)null).equals(someString) // NPE always

I guess the test *could* be made:

static boolean isReferenceNull(Object ref) {
try {
ref.getClass(); // NPE if ref is null
return false; // no NPE -> not null
}
catch (NullPointerException ex) {
return true; // only one way to get here
}
}

... but this is vile.

Also the compiler cannot determine whether two objects have semantically
"equal value", and so the programmer would have to provide code, which would
force the addition of operator overloading (to overload the == operator).

- Oliver
 

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

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top