Not working String comparison in Java - java

This code is not working:
String name = "Bob";
String name1 = "Anne";
if name = name1;
System.out.println ("Hello");
I am a beginner in Java, please help we with this code. I am trying to compare two strings.

You want:
if (name.equals(name1))
Note that you don't want
if (name == name1)
which would be syntactically correct, but would compare the two string references for equality, rather than comparing whether the objects involved represent the same sequence of characters
Further, note that even the top version will simply perform an ordinal comparison of the UTF-16 code units in the string. If the two strings logically represent the same characters but are in different forms, you may not get the result you expect. If you want to do a culture-sensitive comparison, you should look at Collator.
Additionally, I'd recommend that if you're really new to Java, you start off with console apps and/or unit tests to explore the language instead of JSP - it'll give you a much smoother cycle while you're learning the basics, and a simpler environment to work in.
Even more additionally, the code given at the top will throw a NullPointerException if name is a null reference. You should consider what you want to happen at that point - if the string being null would represent a bug anyway, then the exception is probably appropriate; otherwise, you might want to change the code. One useful method in Guava (which is chock full of good stuff) is Objects.equal:
if (Objects.equal(name, name1))
The method return true if both arguments are null, false if exactly one argument is null, and the result of calling equals() if they're both non-null. Very handy.

Your Mistakes :
You are using "=" operator to compare strings. It is not a conditional operator, it is an Assignment operator. The conditional operator in Java is "==" which is used to compare two values if they are equal or not. You even cannot use this one for Strings.
You are writing like this :
if name = name1;
System.out.println ("Hello");
You have put a semi-colon at the end of if statement. So it will do nothing (if your condition is supposed to be right, which is not in this case) however the condition is true or not.
You are missing parantheses around the condition given in if statement.
Synatx of if statement is : if(condition)
So it is must to write "()" around your condition.
Now, for comparing Strings, String class gives us methods like :
stringOne.equals(stringTwo)
It checks for exactly the same string.
or
stringOne.equalsIgnoreCase(stringTwo)
It will ignore Caps-Small letter case.

You must compare the two variables like this
if (name.equals(name1))
This should work and not the way you did it!!!

if(name.equals(name1))
System.out.println("Hello");
== works only when you compare primitives like int or long.
If you want to compare String you have to use either equals() or compareTo(). Single = is an assignment not comparison by doing name=name1 you essentially assign string name1 to variable name.

Your posted code isn't really Java. In addition, you don't compare '==' with the assignment operator '='. Finally, to do proper comparison of 'Object's or anything descended from Objects you need to use the .equals(...) method.
Comparing with == means "is the same object", not "is an object with the same value". The difference seems to be small; but, if you opt to compare objects by their value, it is not small at all. Two Objects can be created with identical "values", and only .equals(...) allows you to consider those two Objects to be the same.

Related

Particularities of strings vs other objects

I'm into Java since a short time, and I was wondering: Strings are in fact objects, but I heard that in assigning them a value and retrieving it they act quite differently, almost as if they were primitive types... could someone make it more clear?
What do I exactly have to care about when I declare/edit/access a string compared to other objects?
First of all Java has string literals. That means you may write String foo = "bar";.
String are immutible (once you create one, you can't change it) and it helps JVM to do one trick called "string pool". String literals are stored in pools, and in the following example both foo and bar may point to one instance of string. String foo = "baz"; String bar = "baz". You may even compare them with ==, but you should never do that. How ever, equals() method (which you use to compare strings in Java) may benefit from it since it does not need to compare strings if both vars point to the same string.
Please check this topic for more info What is the Java string pool and how is "s" different from new String("s")?

What use does the == operator have for String?

In Java, if one is to check if two Strings are equal, in the sense that their values are the same, he/she needs to use the equals method. E.g. :
String foo = "foo";
String bar = "bar";
if(foo.equals(bar)) { /* do stuff */ }
And if one wants to check for reference equality he needs to use the == operator on the two strings.
if( foo == bar ) { /* do stuff */ }
So my question is does the == operator have it's use for the String class ? Why would one want to compare String references ?
Edit:
What I am not asking : How to compare strings ? How does the == work ? How does the equals method work?
What I am asking is what uses does the == operator have for String class in Java ? What is the justification of not overloading it, so that it does a deep comparison ?
Imagine a thread-safe Queue<String> acting as a communication channel between a producer thread and a consumer thread. It seems perfectly reasonable to use a special String to indicate termination.
// Deliberate use of `new` to make sure JVM does not re-use a cached "EOT".
private static final String EOT = new String("EOT");
...
// Signal we're done.
queue.put(EOT);
// Meanwhile at the consumer end of the queue.
String got = queue.get();
if ( got == EOT ) {
// Tidy shutdown
}
note that this would be resilient to:
queue.put("EOT");
because "EOT" != EOT even though "EOT".equals(EOT) would be true.
What use is there for it? Not much in normal practice but you can always write a class that operates on intern()-ed strings, which can then use == to compare them.
Why it isn't overloaded is a simpler question: because there is no operator overloading in Java. (To mess things up a bit, the + operator IS sort of overloaded for strings, which was done to make string operations slightly less cumbersome. But you can argue that's just syntactic sugar and there certainly is no operator overloading in Java on the bytecode level.)
The lack of an overloaded == operator made the use of the operator much less ambiguous, at least for reference types. (That is, until the point autoboxing/unboxing was introduced, which muddies the waters again, but that's another story.) It also allows you to have classes like IdentityHashMap that will behave the same way for every object you put into it.
Having said all that, the decision to avoid operator overloading (where possible) was a fairly arbitrary design choice.
The == operator compares the reference between two objects. For example, if String x and String y refers to two different things, then the == operator will show false. However, the String.equals() method compares not if they refer to each other, but if the values (ex. "Hello", "World", etc.) are the same.
// A.java
String foo1 = "foo";
// B.java
String bar1 = "foo";
All String literals realized at compile time are added to String Constant Pool. So when you have two different String declarations in two different classes, two String objects will not be created and both foo1 & bar1 refer to the same String instance of value foo. Now that you have same String reference in two different variables, you can just check if those two strings are equal just by using == which is fast because all it does is compare the bit pattern, where as in equals() method, each character is compared and is generally used for two different String instances but same content.
In fact, if you look at equals() implementation in String class, the first check they do is Reference comparison using == because they might seem as different instances to you, but if they're String literals or if they're interned by someone else already, then all you have is a Single reference in two variables.
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
// remaining code
}
Also, == is not just for Strings, it's used to compare any two bit patterns, be it primitives or references
1."=="operation of comparison are the values of the two variables are equal, for a reference type variables is expressed by the two variables in the heap memory address is the same, namely the stack have the same content.
2."equals"Whether the two operation variables represent references to the same object in the heap, i.e. whether the contents of the same.
String s = "string1"; creates 1 reference and 1 object in pool String
s1 = "string1"; creates just 1 reference and points to what s is
pointing to.
s == s1 // true
String s2 = new String("string1"); creates 1 object in heap, one in
pool and one reference.
//Since, s2 is pointing to different object so,
s2 == s // false
s1 == s // false
Problem :
So, suppose We want to check, how many unique String object is created and stored in pool by the application while it is running,
We can have a singleton object which can have all the String references stored in an array.
From the previous examples of s, s1 and s2, finally for s and s1, 1 object is created and for s2, 1 object (in total 2).
//If we use equals method, all
s.equals(s1) // gives true
s1.equals(s2) // gives true
//So, number of references present in the array of singleton object will be our
//total number of objects created which equals to 3 // doesn't match actual
//count which is 2
we can use == to check for equality of reference, so if reference is equal, we will not increment our count of unique String object in pool, and for every non equal result, we will increment the count.
here,
for
s // count = 1
s1 == s // count remains same
s2 == s // false, so count = 1 + 1 = 2
//We get total number of unique String objects created and got stored in pool using ==
Simple answer...
Why would one want to compare String references ?
Because they want to compare String values in a very fast way.
Strings are not always interned(). String constants are, but it is possible that the string was created manually on the heap. Using the intern() on a manually created string allows us to to continue using reference comparison on our strings for value comparison.
What is the justification of not overloading it, so that it does a deep comparison ?
Because Java does not have operator overloading as a design decision
Operator '==' is a reference operator always, and equals() is a value method always. In C++ you can change that, but many feel that simply obfuscates the code.
Checking references is Faster compared to checking the entire Strings' equality.
Assume you have Large Strings (URLs or DBMS queries), a have multiple references to them. To check if they are equal, either you can check character by character or you can check if they both refer to the same object.
In fact, equals method in java first checks if the references are same and only if not goes ahead and checks character by character.
Java is full of references and hence, you might need a case where you need to check if two variables are referring to the same String/Object rather than both having each copy of the same String so that you can update string at one place and it reflects in all variables.
To do so, equals method does not help as it checks the copies to be equal as well. you need to check if they both refer to the same object and hence == comes into picture.
It seems that this was asked before and received quite a popular answer here:
Why didn't == operator string value comparison make it to Java?
The simple answer is: consistency
I guess it's just consistency, or "principle of least astonishment".
String is an object, so it would be surprising if was treated
differently than other objects.
Although this is not the fundamental reason, a usage could be to improve performances: before executing a heavy computation, "internalize" your Strings (intern()) and use only == for comparisons.
What I am asking is what uses does the == operator have for String class in Java ?
What is the justification of not overloading it, so that it does a deep comparison ?
== and equals have altogether different uses.
== confirms if there is reference-equality
Equals confirms if the objects contains are same.
Example of reference-equality is IdentityHashMap.
There could be a case in which Only the object inserting something to IdentityHashMap has the right to get/remove the object.
overloading reference-equality can lead to unwanted complexity for java.
for example
if (string)
{
do deep equality
}
else
{
do reference-equality
}
/*****************************************************************/
public class IdentityHashMap extends AbstractMap implements Map, Serializable, Cloneable
This class implements the Map interface with a hash table, using reference-equality in place of object-equality when comparing keys (and values). In other words, in an IdentityHashMap, two keys k1 and k2 are considered equal if and only if (k1==k2). (In normal Map implementations (like HashMap) two keys k1 and k2 are considered equal if and only if (k1==null ? k2==null : k1.equals(k2)).)
This class is not a general-purpose Map implementation! While this class implements the Map interface, it intentionally violates Map's general contract, which mandates the use of the equals method when comparing objects. This class is designed for use only in the rare cases wherein reference-equality semantics are required.

I don't understand this ("string" == "string") example

I found this java code on a java tutorial page:
if ("progress" == evt.getPropertyName())
http://download.oracle.com/javase/tutorial/uiswing/examples/components/index.html
How could this work? I thought we HAVE TO use the equals() method for this situation (string.equals("bla"))? Could we use equals() here too? Would it be better? Any ideas?
Edit: So IF equals() would be better, then I really don't understand why a serious oracle tutorial page didn't use it? Also, I don't understand why it's working because I thought a string is an object. If I say object == object, then that's a big problem.
Yes, equals() would definitely be better and correct. In Java, a pool of string constants is maintained and reused intelligently for performance. So this can work, but it is only guaranteed if evt.getPropertyName() is assured to return constants.
Also, the more correct version would be "progress".equals(evt.getPropertyName()), in case evt.getPropertyName() is null. Note that the implementation of String.equals starts with using == as a first test before doing char-by-char comparison, so performance will not be much affected versus the original code.
Which demo are we looking at?
This explains equals() vs ==
http://www.java-samples.com/showtutorial.php?tutorialid=221
It is important to understand that the equals( ) method and the == operator perform two different operations. As just explained, the equals( ) method compares the characters inside a String object. The == operator compares two object references to see whether they refer to the same instance. The following program shows how two different String objects can contain the same characters, but references to these objects will not compare as equal:
So in your particular example, it is comparing the reference to see if they are the same reference, not to see if the string chars match I believe.
The correct version of this code should be:
if ("progress".equals(evt.getPropertyName()))
This could work because of the way that the JVM handles string constants. Each string constant is intern()ed. So if evt.getPropertyName() is returning a reference to a string constant than using == will work. But it is bad form and in general it will not work.
This only would work if evt.getPropertyName() returns a constant string of value "progress".
With constant string, I mean evaluated at compile-time.
In most cases, when comparing Strings, using equals is best. However, if you know you'll be comparing the exact same String objects (not just two strings that have the same content), or if you're dealing entirely with constant Strings and you really care about performance, using == will be somewhat faster than using equals. You should normally use equals since you normally don't care about performance sufficiently to think about all the other prerequisites for using ==.
In this case, the author of the progress demo should probably have used equals - that code isn't especially performance-critical. However, in this particular case, the code will be dealing entirely with constant strings, so whilst it's probably not the best choice, especially for a demo, it is a valid choice.

java if statement error

It seems to me that this if statement is not working.
I'm new in java, but i know C# and C++ pretty well, but I've never seen such a thing before:
today=edit[0].substring(0,10);
if (today == edit[0].substring(0,10))
{
pars_prog.addView(name_prog[i]);
}
And it doesn't get into the IF function?
Are if statements different in Java (Android)?
When you use == for any object references (whether strings or any other non-primitive type) it simply compares whether the references are equal - i.e. whether they refer to the exact same object, or whether they're both null.
In this case, you want to determine whether the strings are equal - i.e. whether they represent the same sequence of characters. You should use the equals method for that:
if (today.equals(edit[0].substring(0,10)))
However, in general when doing this you should be careful that the target of the equals call is non-null, or you'll get a NullPointerException.
Note that C# is similar - except that the == operator can be overloaded, and is overloaded for string. If the compile-time types of the operands aren't both string, you'll still get reference comparison:
object text1 = new StringBuilder("hello").ToString();
object text2 = new StringBuilder("hello").ToString();
Console.WriteLine(text1 == text2); // False
You are trying to compare strings with ==, which is identity comparison - it will check if the two are the same instance (in the JVM) rather than comparing their contents.
Use today.equals(..) instead.
That said, if appears you are working with dates, so a String is not the best way to handle this. Use Calendar, Date (a bit obsolete) or joda-time DateTime
You have to use the equals method when comparing strings.. Right now you are comparing references and thats why you never enter the if block

Why doesn't Java warn about a == "something"?

This might sound stupid, but why doesn't the Java compiler warn about the expression in the following if statement:
String a = "something";
if(a == "something"){
System.out.println("a is equal to something");
}else{
System.out.println("a is not equal to something");
}
I realize why the expression is untrue, but AFAIK, a can never be equal to the String literal "something". The compiler should realize this and at least warn me that I'm an idiot who is coding way to late at night.
Clarification
This question is not about comparing two String object variables, it is about comparing a String object variable to a String literal. I realize that the following code is useful and would produce different results than .equals():
String a = iReturnAString();
String b = iReturnADifferentString();
if(a == b){
System.out.println("a is equal to b");
}else{
System.out.println("a is not equal to b");
}
In this case a and b might actually point to the same area in memory, even if it's not because of interning. In the first example though, the only reason it would be true is if Java is doing something behind the scenes which is not useful to me, and which I can't use to my advantage.
Follow up question
Even if a and the string-literal both point to the same area in memory, how is that useful for me in an expression like the one above. If that expression returns true, there isn't really anything useful I could do with that knowledge, is there? If I was comparing two variables, then yes, that info would be useful, but with a variable and a literal it's kinda pointless.
Actually they can indeed be the same reference if Java chooses to intern the string. String interning is the notion of having only one value for a distinct string at runtime.
http://en.wikipedia.org/wiki/String_intern_pool
Java notes about string interning
http://javatechniques.com/blog/string-equality-and-interning/
Compiler warnings tend to be about things that are either blatantly wrong (conditionals that can never be true or false) or unsafe (unchecked casts). The use of == is valid, and in some rare cases intentional.
I believe all of Checkstyle, FindBugs and PMD will warn about this, and optionally a lot of other bad practices we tend to have when half asleep or otherwise incapacitated ;).
Because:
you might actually want to use ==, if working with constants and interned strings
the compiler should make an exception only for String, and no other type. What I mean is - whenever the compiler encounters == it should check if the operands are Strings in order to issue a warning. What if the arguments are Strings, but are referred to as Object or CharSequence ?
The rationale given by checkstyle for issuing an error is that novice programmers often do this. And if you are novice, I'd be hard to configure checkstyle (or pmd), or even to know about them.
Another thing is the actual scenario when strings are compared and there is a literal as one of the operands. First, it would be better to use a constant (static final) instead of a literal. And where would the other operand come from? It is likely that it will come from the same constant / literal, somewhere else in the code. So == would work.
Depending on the context, both identity comparisons and value comparisons can be legitimate.
I can think of very few queries where there is a deterministic automated algorithm to figure out unambiguously that one of them is an error.
Therefore, there's no attempt to do this automatically.
If you think about things like caching, then there are situations where you would want to do this test.
Actually, it may sometimes be true, depending on if Java takes an existing String from its internal String cache, creating the first declaration and then storing it, or taking it for both string declarations.
The compiler doesn't care that you're trying to do identity comparison against a literal. It could also be argued that it's not the compiler's job to be a code nanny. Look for a lint-like tool if you want to catch situations like this.
"I realize why the expression is untrue, but AFAIK, a can never be equal to the String literal "something"."
To clarify, in the example given, the expersion is always TRUE and a can be == and equals() to the String literal and in the example given it is always == and equals().
It is ironic that you appear have given the rare counter example to your own argument.
There are cases where you actually care whether you're dealing with exactly the same object rather than whether two objects are equal. In such cases, you need == rather than equals(). The compiler has no way of knowing whether you really wanted to compare the references for equality or the objects that they point to.
Now, it's far less likely that you're going to want == for strings than it would be for a user-defined type, but that doesn't guarantee that you wouldn't want it, and even if it did, that means that the compiler would have to special case strings are specifically check to make sure that you didn't use == on them.
In addition, because strings are immutable, the JVM is free to make string which would be equal per equals() share the same instance (to save memory), in which case they would also be equal per ==. So, depending on what the JVM does, == could very well return true. And the example that you gave is actually one where there's a decent chance of it because they're both string literals, so it would be fairly easy for the JVM to make them the same string, and it probably would. And, of course, if you want to see whether the JVM is making two strings share the same instance, you would have to use == rather than equals(), so there's a legitimate reason to want to use == on strings right there.
So, the compiler has no way of knowing enough of what you're doing to know that using == instead of equals() should be an error. This can lead to bugs if you're not careful (especially if you're used to a language like C++ which overloads == instead of having a separate equals() function), but the compiler can only do so much for you. There are legitimate reasons for using == instead of equals(), so the compiler isn't going to flag it as an error.
There exist tools that will warn you about these constructs; feel free to use them. However there are valid cases when you want to use == on Strings, and it is much worse language design to warn a user about a perfectly valid construct than to fail to warn them. When you have been using Java a year or so (and I will bet good money that you haven't reached that stage yet) you will find avoiding constructs like this is second nature.

Categories

Resources