I know that == has some issues when comparing two Strings. It seems that String.equals() is a better approach. Well, I'm doing JUnit testing and my inclination is to use assertEquals(str1, str2). Is this a reliable way to assert two Strings contain the same content? I would use assertTrue(str1.equals(str2)), but then you don't get the benefit of seeing what the expected and actual values are on failure.
On a related note, does anyone have a link to a page or thread that plainly explains the problems with str1 == str2?
You should always use .equals() when comparing Strings in Java.
JUnit calls the .equals() method to determine equality in the method assertEquals(Object o1, Object o2).
So, you are definitely safe using assertEquals(string1, string2). (Because Strings are Objects)
Here is a link to a great Stackoverflow question regarding some of the differences between == and .equals().
assertEquals uses the equals method for comparison. There is a different assert, assertSame, which uses the == operator.
To understand why == shouldn't be used with strings you need to understand what == does: it does an identity check. That is, a == b checks to see if a and b refer to the same object. It is built into the language, and its behavior cannot be changed by different classes. The equals method, on the other hand, can be overridden by classes. While its default behavior (in the Object class) is to do an identity check using the == operator, many classes, including String, override it to instead do an "equivalence" check. In the case of String, instead of checking if a and b refer to the same object, a.equals(b) checks to see if the objects they refer to are both strings that contain exactly the same characters.
Analogy time: imagine that each String object is a piece of paper with something written on it. Let's say I have two pieces of paper with "Foo" written on them, and another with "Bar" written on it. If I take the first two pieces of paper and use == to compare them it will return false because it's essentially asking "are these the same piece of paper?". It doesn't need to even look at what's written on the paper. The fact that I'm giving it two pieces of paper (rather than the same one twice) means it will return false. If I use equals, however, the equals method will read the two pieces of paper and see that they say the same thing ("Foo"), and so it'll return true.
The bit that gets confusing with Strings is that the Java has a concept of "interning" Strings, and this is (effectively) automatically performed on any string literals in your code. This means that if you have two equivalent string literals in your code (even if they're in different classes) they'll actually both refer to the same String object. This makes the == operator return true more often than one might expect.
In a nutshell - you can have two String objects that contain the same characters but are different objects (in different memory locations). The == operator checks to see that two references are pointing to the same object (memory location), but the equals() method checks if the characters are the same.
Usually you are interested in checking if two Strings contain the same characters, not whether they point to the same memory location.
public class StringEqualityTest extends TestCase {
public void testEquality() throws Exception {
String a = "abcde";
String b = new String(a);
assertTrue(a.equals(b));
assertFalse(a == b);
assertEquals(a, b);
}
}
The JUnit assertEquals(obj1, obj2) does indeed call obj1.equals(obj2).
There's also assertSame(obj1, obj2) which does obj1 == obj2 (i.e., verifies that obj1 and obj2 are referencing the same instance), which is what you're trying to avoid.
So you're fine.
Yes, it is used all the time for testing. It is very likely that the testing framework uses .equals() for comparisons such as these.
Below is a link explaining the "string equality mistake". Essentially, strings in Java are objects, and when you compare object equality, typically they are compared based on memory address, and not by content. Because of this, two strings won't occupy the same address, even if their content is identical, so they won't match correctly, even though they look the same when printed.
http://blog.enrii.com/2006/03/15/java-string-equality-common-mistake/
"The == operator checks to see if two Objects are exactly the same Object."
http://leepoint.net/notes-java/data/strings/12stringcomparison.html
String is an Object in java, so it falls into that category of comparison rules.
Related
This question already has answers here:
comparing arrays in java
(6 answers)
Closed 1 year ago.
I have a program with 2 classes - a Node class and a Problem class.
The Problem class has an PriorityQueue attribute.
The Node class has an char [] state attribute.
I'm trying to run a function at the Problem class with the next input:
(Node node , PriorityQueue q) and check if there is any node in q with the same state as the node. state
public boolean insideQueue (Node node, PriorityQueue<Node> q){
for (Node ele : q) {
if(ele.state == node.state) {
return true;
}
}
return false;
}
I tried to use toString() method to solve the problem, and Im having a problem to understand how I can solve this problem with another way (maybe because I'm using python 95% of my time)
I'm adding a photo from my debugger.
Thank you very much
Java == compares the object references for you, which are char[7]#840 and char[7]#835, so they are different.
Converting to String, and comparing the result as a.equals(b) could work (== would not), but there are pre-defined methods for comparing arrays in the Arrays class, https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#equals(char[],%20char[]) is the one you could use in particular, so
if(ele.state == node.state) {
becomes
if(Arrays.equals(ele.state, node.state)) {
I have absolutely no idea what you mean by
skipping a condition scope in java
However, the code you wrote makes no sense, so presumably the problem with it is what you're struggling with.
A char[] is a java array; an object (all things in java are objects, except primitives, which are a hardcoded list of 8 types: int, double, boolean - the lowercased stuff. char is a primitive, but arrays of primitives are objects).
All expressions that resolve to an object type are references - they are like an entry in a phone book, and not the phone itself. Merely instructions on how to get there.
== in java compares the raw value. For primitives, that just compares values, but for references (and, remember, all expressions of non-primitive types are references), it compares references, i.e. it doesn't check if it's the same phone number, it checks if it's the same entry in the same phone book.
You can therefore have 2 different objects whose contents are identical; with ==, that would return false, because == checks if they are the same object reference, not if the content inside them is equal.
For that you ordinarily want .equals, but arrays in java are low-level primitive things designed for speed and for access to low-level hardware, and not for actual normal use. I have no idea why you don't just have strings here. At any rate, for normal objects, you just call .equals() on it. For arrays, no such luck, their equals method also is a check for same object identity (for somewhat solid reasons). To compare content, you need Arrays.equals.
So:
if (Arrays.equals(ele.state, node.state)) { ... }
will return true even if ele.state and node.state are pointing at different char arrays, but those char arrays have the exact same content. Which, according to your debugger paste, they do.
Alternatively, don't use arrays unless you really know what you are doing. Those should be strings. Then all you really need is ele.state.equals(node.state).
I can see that contentEquals is useful for comparing char sequences but I can't find anywhere specifying which method is the best to use when comparing two strings.
Here mentions the differences between both methods but it doesn't explicitly say what to do with two strings.
I can see one advantage of usng contentEquals is that if the variable passed in has its type changed, a compilation error will be thrown. A disadvantage could be the speed of execution.
Should I always use contentEquals when comparing strings or only use it if there are different objects extending CharSequence?
you should use String#equals when comparing the content fo two Strings. Only use contentEquals if one of the Object is not of the type String.
1) it is less confusing. Every Java developer should know what the method is doing, but contentEquals is a more specialised method and therefore less known.
2) It is faster, as you can see in the implementation of contentEquals it calls equals after checking if the sequence is of type AbstractStringBuilder so you save the execution time of that check. But even if the execution would be slower this should not be the first point to make your decision on. First go for readability.
The advantage of contentEquals() is support for objects that implement a CharSequence. When you have a StringBuilder it would be wasteful to call StringBuilder.toString() just so you can use equals() a moment later. In this case contentEquals() helps to avoid allocating a new String to do the comparison.
When comparing two String objects just use equals().
I have a function in one of my classes that compares itself with another instance of the same class - and finds out which variables differ. This is for the purpose of minimizing network load with a main database (by only uploading data that needs to be uploaded, instead of uploading the whole object).
For this, I have been trying to make use of the object.equals() function to compare the two objects.
I soon found that the object.equals() does not handle nulls, and after reading this question, I understand why.
So an example of my broken code is as follows:
public class MyObject {
String myString;
String myString2;
public String getChangedVars(MyObject comparisonObj) {
ArrayList<String> changedVars = new ArrayList<String>();
if (!this.myString.equals(comparisonObj.myString))
changedVars.add("myString");
if (!this.myString2.equals(comparisonObj.myString2))
changedVars.add("myString2");
return changedVars.toString();
}
}
My question is - on the basis that either one of the variables being compared could be null, what is a simple way to compare two variables whilst avoiding a NullPointerException?
Edit:
Simply checking for null on both objects first doesn't work well, as I still want to compare if the object has a reference or not. Eg, if one item is null and the other is not, I want this to resolve to true, as the variable has changed.
There is new utility class available in jdk since 1.7 that is Objects .
This class consists of static utility methods for operating on
objects. These utilities include null-safe or null-tolerant methods
for computing the hash code of an object, returning a string for an
object, and comparing two objects.
You can use Objects.equals, it handles null.
Objects.equals(Object a, Object b) Returns true if the arguments are equal to each other and false
otherwise. Consequently, if both arguments are null, true is returned
and if exactly one argument is null, false is returned. Otherwise,
equality is determined by using the equals method of the first
argument.
if(Objects.equals(myString,myString2)){...}
You can use Apache object utils
ObjectUtils.equals(Object object1, Object object2) -- Returns boolean
this method has been replaced by java.util.Objects.equals(Object, Object) in Java 7
if (this.myString != null && this.myString.equals(comparisonObj.myString))
{
changedVars.add("myString");
}
Use StringUtils provided by apache
StringUtils.equals(myString,comparisonObj.myString);
I'm testing out the JSON functionality for an Android application and have the following JSON object.
{"result":"fail"}
I then use the following code to get my value:
JSONObject jObject = new JSONObject(ReturnValue); //Return value is what's shown above
String r = jObject.getString("result");
Then using the following I don't get a match
if(r.trim() == "fail")
I wrote it out to the screen just to make sure with this:
et.setText("-" + r + "-");
That results in -fail-
I don't understand why this doesn't match. If I used r.Contains it returns true, but I can't use that for my checks.
Use equals .equals instead of ==. This is because of in Java, if you use == you compare the Object pointers to each other. In the source code of String they have overriden the equals method so they instead compare the letters.
You can't override operators in Java.
Also this is general, always use equals for any object comparison if you don't want to check the references you are comparing are actually pointing on the same object in the heap.
Use
if(r.trim().equals("fail"))
to compare Strings.
as others pointed out, in Java == means "exactly the same object", not "an identical object". You can have two, say, SimpleDateFormat objects that are identical, yet if they occupy different places on the heap, they are not the same object. fyi, C# behaves in quite similar way, but manages to hide it from programmers most of the time.
btw, Since you are already writing Java code, it might be a good idea to, you know, study the language a bit. Saves an awful lot of problems later on. A lot of other surprises await for people who try to write C# in Java (like non-static inner classes).
Found the following in my notes, but I am unable to make sense of it:
Primitive type wrapper classes implement caching for a limited number
of values.
This guarantees that a limited number of deeply equal wrapper objects are
also shallowly equal:
If o1.equals( o2 ) then o1 == o2.
For example, new Integer( 0 ) == new Integer( 0 ).
In general this does not always work.
For example, new Integer( 666 ) == new Integer( 666 )
may not hold.
The reason for caching is that it saves memory.
In general caching works for “small” primitive values.
I don't understand what is meant by this, or what the difference is between a deep (.equals()) and shallow(==) equals. I know in practice, .equals must be used to objects and == for Integral values, but the actual reasoning for this alludes me.
I assume by the names that shallow maybe just checks that both the values are of the same type and name, which deep checks that both variables point to the same object? I don't see how the caching would come into play here though, or why it would be useful.
When you do == you are comparing the references for equality. This means you're saying "is the address in memory the same for both Objects?"
When you do .equals() you are comparing the Objects themselves for equality. This means you're saying "do these two Objects consider themselves equal?"
The example that was given was poor. The only caching done for these numbers that's mandated by the JLS is the .valueOf() method. The constructor is not cached.
Furthermore, the JLS only specifies the minimum you must cache [-128:127]. JVM implementations may cache more if they so choose. This means Integer.valueOf(500) == Integer.valueOf(500) may be false on some machines, but true on others.
class biziclop {
public static void main(String[] args) {
System.out.println(new Integer(5) == new Integer(5));
System.out.println(new Integer(500) == new Integer(500));
System.out.println(Integer.valueOf(5) == Integer.valueOf(5));
System.out.println(Integer.valueOf(500) == Integer.valueOf(500));
}
}
Results in:
C:\Documents and Settings\glow\My Documents>java biziclop
false
false
true
false
C:\Documents and Settings\glow\My Documents>
See a more detailed answer here (the comments are a gem!): Why do people still use primitive types in Java?
Well, actually shallow/deep dissection is different from ==/equal dissection:
== compares for object identity, that is you checking whether
operands are the same in fact
(two references to the same area of memory),
whereas equals compares for object
equivalence, that is "logical" value
of two, possibly not identical
objects, is the same. If for two
objects
a == b
then it's true that
a.equals(b) // if a != null
, but opposite isn't true in all
cases.
shallow/deep distinction makes sense
only for equals comparison.
Shallow means that you compare only
immediate contents of two objects to
find whether they "equal" in your
sense, whereas deep means that you
compare contents of your objects
recursively until all you need to
compare is primitive fields. If
you define equals method of your
objects as sequence of calls to
equals on instance fields of these
objects, you use deep comparison. If
you define equals using ==
operator to compare compound types,
such as Strings, then you use shallow comparison -- and that's incorrect in Java.
Morale of all of this is that you must never use == to compare two compound objects, unless you consider them equal only if they are the same.
What you call "shallow equal" is identity: two references (i.e. objects) are identical if they are the very same instances. If you know what pointers are in other languages, you can compare identity to pointer equality.
What you call "deep equal" is equality: two objects a and b are equal if a.equals(b) returns true (and hopefully vice versa). The correctness of equality strongly depends on the way the equals method is implemented. See the Javadoc of the Object class for more details.
First off: new Integer(0) == new Integer(0) will never evaluate to true, as new always creates a new object, sidestepping any autoboxing-caching mechanism that might exist.
What you probably heard about was autoboxing (i.e. automatic conversion of primitive values to their respective wrapper classes when necessary). Autoboxing uses a mechanism that's also accessible using the wrapper classes valueOf() methods. In other words: auto-boxing an int to an Integer works pretty much the same as calling Integer.valueOf(int).
Integer.valueOf(0) == Integer.valueOf(0) will evaluate to true, because common values (i.e. values with a low absolute value) are cached. You'll get the same Integer object when you call valueOf(0) twice in a row. This is not necessarily true with higher values (such as 666 in your example).
equals() tests whether two objects are essentially the same, but it can return true for two distinct objects; i.e., two different paper clips are "equals". "==" for reference types tests whether two references refer to the same object -- i.e., a paper clip is == only to itself. == tests identity, which equals tests equivalence.
You could have two distinct Integer objects with a 0 in them (they are equals()); caching means saving objects and reusing them when possible.