Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > Catching invalid string comparisons

Reply
Thread Tools

Catching invalid string comparisons

 
 
Ulrich Eckhardt
Guest
Posts: n/a
 
      04-09-2008
Greetings!

I guess many of you have already seen code (especially from C++ programmers)
like the following:

String s = someFunction();
if(s == "0")
doThis();
else
doThat();

I wonder, is there a way to catch such comparisons where a non-fundamental
type is compared to a constant? I'm actually looking for a way to avoid
errors that occur due to this, maybe a warning when a comparison is done
for identity where one of the two sides required boxing (Is that the term?)
first.

Further, I wonder about this case:

Integer n = otherFunction();
if(n == 42)
dontPanic();

Other than the above, I haven't actually tried it, but I would expect this
code to also not do what a naive programmer would expect.


Just for the record, in case you didn't spot the problem in above code, this
is how the above should be written:

if(s.equals("0")) ...
if(n.equals(42)) ...
// Note: I'm not sure about the latter.

The reason is that '==' determines identity for objects while it determines
equality for builtin types like 'int' (please correct me if I'm wrong or if
this explanation is misleading in any way).

thanks

Uli

--
Sator Laser GmbH
Geschäftsführer: Michael Wöhrmann, Amtsgericht Hamburg HR B62 932

 
Reply With Quote
 
 
 
 
Ulrich Eckhardt
Guest
Posts: n/a
 
      04-09-2008
Lew wrote:
> Ulrich Eckhardt wrote:
>> Greetings!
>>
>> I guess many of you have already seen code (especially from C++
>> programmers) like the following:
>>
>> String s = someFunction();
>> if(s == "0")
>> doThis();
>> else
>> doThat();
>>
>> I wonder, is there a way to catch such comparisons where a
>> non-fundamental type is compared to a constant? I'm actually looking for
>> a way to avoid errors that occur due to this, maybe a warning when a
>> comparison is done for identity where one of the two sides required
>> boxing (Is that the term?) first.

>
> There is no boxing with Strings, and String is a pretty fundamental type,
> so I'm not quite sure I get these comments.


Bear with me, I probably didn't express myself correctly because I'm not
that fluent in Java.

The problem I'm facing is this:

String s1 = "foo";
String s2 = s1.substring(1,1); // yields empty string!
if(s2 == "")
System.out.println("s2 is empty");
else
System.out.println("s2 is not empty");

This code actually checks if s2 is identical to an empty string literal, but
the programmer expected it to check if it is equal to an empty string.

> Anyhow, it's usually a mistake to compare String values with ==, except
> when comparing against null. It's such a common mistake that IDEs
> include an option to warn you of it.
>
>> Further, I wonder about this case:
>>
>> Integer n = otherFunction();
>> if(n == 42)
>> dontPanic();
>>
>> Other than the above, I haven't actually tried it, but I would expect
>> this code to also not do what a naive programmer would expect.

>
> What would a naive programmer expect? What do you expect this snippet to
> do?


Actually, I would expect this to behave just like the code using a string
above, i.e. that it checks if 'n' is identical to the integer literal '42'
and not if they are equal, but that is because I know that Java makes this
distinction between identity and equality.

Note that I find this behaviour a bit confusing, because if I had written it
like this:

int n = yetAnotherFunction();
if(n == 42)
doPanic();

really checks if 'n' is equal to '42', right?


>> Just for the record, in case you didn't spot the problem in above code,
>> this is how the above should be written:
>>
>> if(s.equals("0")) ...
>> if(n.equals(42)) ...

>
> The 's' case is correct, but the 'n' case is just silly.


Why silly? I don't get it. To me it's the same principle in both cases, in
order to compare an object (like String or Integer) for equality with a
constant, you use the equals() function and _not_ ==, which would check for
identity.


Uli

--
Sator Laser GmbH
Geschäftsführer: Michael Wöhrmann, Amtsgericht Hamburg HR B62 932

 
Reply With Quote
 
 
 
 
blmblm@myrealbox.com
Guest
Posts: n/a
 
      04-09-2008
In article <(E-Mail Removed)>,
Ulrich Eckhardt <(E-Mail Removed)> wrote:
> Lew wrote:
> > Ulrich Eckhardt wrote:


[ snip ]

> The problem I'm facing is this:
>
> String s1 = "foo";
> String s2 = s1.substring(1,1); // yields empty string!
> if(s2 == "")
> System.out.println("s2 is empty");
> else
> System.out.println("s2 is not empty");
>
> This code actually checks if s2 is identical to an empty string literal, but
> the programmer expected it to check if it is equal to an empty string.
>
> > Anyhow, it's usually a mistake to compare String values with ==, except
> > when comparing against null. It's such a common mistake that IDEs
> > include an option to warn you of it.
> >
> >> Further, I wonder about this case:
> >>
> >> Integer n = otherFunction();
> >> if(n == 42)
> >> dontPanic();
> >>
> >> Other than the above, I haven't actually tried it, but I would expect
> >> this code to also not do what a naive programmer would expect.

> >
> > What would a naive programmer expect? What do you expect this snippet to
> > do?

>
> Actually, I would expect this to behave just like the code using a string
> above, i.e. that it checks if 'n' is identical to the integer literal '42'
> and not if they are equal, but that is because I know that Java makes this
> distinction between identity and equality.
>
> Note that I find this behaviour a bit confusing, because if I had written it
> like this:
>
> int n = yetAnotherFunction();
> if(n == 42)
> doPanic();
>
> really checks if 'n' is equal to '42', right?
>
>
> >> Just for the record, in case you didn't spot the problem in above code,
> >> this is how the above should be written:
> >>
> >> if(s.equals("0")) ...
> >> if(n.equals(42)) ...

> >
> > The 's' case is correct, but the 'n' case is just silly.

>
> Why silly? I don't get it. To me it's the same principle in both cases, in
> order to compare an object (like String or Integer) for equality with a
> constant, you use the equals() function and _not_ ==, which would check for
> identity.


To me it makes better sense if you realize that the variable s is
not actually a String object, but a *reference to* a String object.
"==" works on such variables exactly the way it works on primitives --
compares for equality -- but two (non-null) references are equal
if, well, they're equal -- which for references means that they
point to the same object. Comparing the objects themselves,
rather than the references, requires use of the equals() method.

Does that help? If you're coming from C++ this behavior will
likely seem baffling at first, but IMO it makes good sense if
you realize that non-primitive variables in Java are references
to objects rather than objects.

--
B. L. Massingill
ObDisclaimer: I don't speak for my employers; they return the favor.
 
Reply With Quote
 
Roedy Green
Guest
Posts: n/a
 
      04-09-2008
On Wed, 09 Apr 2008 11:17:07 +0200, Ulrich Eckhardt
<(E-Mail Removed)> wrote, quoted or indirectly quoted someone
who said :

>I wonder, is there a way to catch such comparisons where a non-fundamental
>type is compared to a constant? I


I'm sure others will give you all sorts of suggestions, but the way I
do it is using the code inspector (lint) that comes with Intellij
Idea. That is just one of thousands of errors or suspect codings it
catches.
--

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
 
Reply With Quote
 
Roedy Green
Guest
Posts: n/a
 
      04-09-2008
On Wed, 09 Apr 2008 11:17:07 +0200, Ulrich Eckhardt
<(E-Mail Removed)> wrote, quoted or indirectly quoted someone
who said :

>
> Integer n = otherFunction();
> if(n == 42)
> dontPanic();
>
>Other than the above, I haven't actually tried it, but I would expect this
>code to also not do what a naive programmer would expect.


If you need boxing and you are using an old Java, the compiler will
complain. If you need boxing and you are using a new compiler it will
autobox for you. So don't worry about that.
--

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
 
Reply With Quote
 
Mark Space
Guest
Posts: n/a
 
      04-09-2008
Matt Humphrey wrote:

> I think what you're saying is that (for the benefit of those less
> experienced with Java) you would like the IDE to highlight cases where == is


I think what he's say is that he'd like the Java compiler to do this,
emit warnings when there's questionable use of == operator. If the IDE
wants to do it also, that's great.
 
Reply With Quote
 
Mark Space
Guest
Posts: n/a
 
      04-09-2008
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

> To me it makes better sense if you realize that the variable s is
> not actually a String object, but a *reference to* a String object.


I agree. 'if ( s == "" )' checks to see if s is the same object as the
null string object that the compiler/runtime has created to represent
your literal. This could actually work, if s has been interned.

String s1 = "foo";
String s2 = s1.substring(1,1); // yields empty string!
s2 = s2.intern();
if(s2 == "")
System.out.println("s2 is empty");
else
System.out.println("s2 is not empty");

I believe this will work (I didn't test it). == compares object
references. It doesn't check to see if two objects are "identical" it
checks to see if they are in fact the same object.

Basically, == does a bit-wise check for identity on any primitive. (Or
at least that's how I think of it, it might actually work differently
internally.) In this respect, comparing references in Java is exactly
like comparing pointers in C.

 
Reply With Quote
 
Mark Jeffcoat
Guest
Posts: n/a
 
      04-09-2008
Ulrich Eckhardt <(E-Mail Removed)> writes:

> I guess many of you have already seen code (especially from C++ programmers)
> like the following:
>
> String s = someFunction();
> if(s == "0")
> doThis();
> else
> doThat();


This (anti-)pattern is common enough that most static
analyzers will check for it. I've had great experiences
with FindBugs (findbugs.sourceforge.net) and PMD
(pmd.sourceforge.net).



--
Mark Jeffcoat
Austin, TX
 
Reply With Quote
 
Ulrich Eckhardt
Guest
Posts: n/a
 
      04-10-2008
(E-Mail Removed) wrote:
> In article <(E-Mail Removed)>,
> Ulrich Eckhardt <(E-Mail Removed)> wrote:
>> Lew wrote:
>> > Ulrich Eckhardt wrote:
>> >> Just for the record, in case you didn't spot the problem in above
>> >> code, this is how the above should be written:
>> >>
>> >> if(s.equals("0")) ...
>> >> if(n.equals(42)) ...
>> >
>> > The 's' case is correct, but the 'n' case is just silly.

>>
>> Why silly? I don't get it. To me it's the same principle in both cases,
>> in order to compare an object (like String or Integer) for equality with
>> a constant, you use the equals() function and _not_ ==, which would check
>> for identity.

>
> To me it makes better sense if you realize that the variable s is
> not actually a String object, but a *reference to* a String object.


Yes, this is a better way to express it.

> "==" works on such variables exactly the way it works on primitives --
> compares for equality -- but two (non-null) references are equal
> if, well, they're equal -- which for references means that they
> point to the same object. Comparing the objects themselves,
> rather than the references, requires use of the equals() method.


Right, I understood that.

> If you're coming from C++ this behavior will likely seem baffling
> at first, but IMO it makes good sense if you realize that non-primitive
> variables in Java are references to objects rather than objects.


Yes, I had to wrap my head around that first, but it makes sense in Java way
of doing things.

However, there is one thing which I don't understand yet:

Integer n = new Integer(42);

'n' is now a reference to an Integer object. So, if I do this:

if(n==42) ...

it should check if 'n' refers to the same object as '42' here. However, it
doesn't, it actually checks if the Integer that 'n' refers to has the same
value, which - to me - seems inconsistent with the String case. Is there a
way to explain this inconsistency so that it makes sense again? Or do I
just have to learn the rules for each type?

thanks

Uli

--
Sator Laser GmbH
Geschäftsführer: Michael Wöhrmann, Amtsgericht Hamburg HR B62 932

 
Reply With Quote
 
Ulrich Eckhardt
Guest
Posts: n/a
 
      04-10-2008
Mark Space wrote:
> (E-Mail Removed) wrote:
>> To me it makes better sense if you realize that the variable s is
>> not actually a String object, but a *reference to* a String object.

>
> I agree. 'if ( s == "" )' checks to see if s is the same object as the
> null string object that the compiler/runtime has created to represent
> your literal. This could actually work, if s has been interned.
>
> String s1 = "foo";
> String s2 = s1.substring(1,1); // yields empty string!
> s2 = s2.intern();
> if(s2 == "")
> System.out.println("s2 is empty");
> else
> System.out.println("s2 is not empty");
>
> I believe this will work (I didn't test it).


In a test, this printed "s2 is not empty", because 's2' doesn't refer to the
same object as '""' does. However, I could well imagine that a smarter
compiler replaces all references to an empty string with references to the
same string, which could then result in the other output.

Uli

--
Sator Laser GmbH
Geschäftsführer: Michael Wöhrmann, Amtsgericht Hamburg HR B62 932

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
invalid character in base-64 string and invalid postback or callba kevin ASP .Net 0 01-16-2008 09:39 PM
Invalid URI: There is an invalid sequence in the string. Error!! Patrick.O.Ige ASP .Net 1 07-02-2006 11:21 AM
cPAMIE/Python String and Date Comparisons Sam R Python 1 11-09-2005 12:59 AM
XPath's with String comparisons gfrommer@hotmail.com Java 1 06-27-2005 10:59 PM
string comparisons Horn C++ 7 10-06-2003 09:49 PM



Advertisments