object equals method being == and shallow copy [duplicate] - java

This question already has answers here:
What is the difference between == and equals() in Java?
(26 answers)
Closed 4 years ago.
I have
Object o = new Object()
o == o.clone(); //I understand this should be false since it's different two arraylist pointing to the same object right?
o.equals(o.clone()) //it's true if it's shallow copy since pointing at the same one
here equals isn't ==, it should be comparing hash code right? since it's object.
source: equals method usage in string and list
but on my notes it says the equal method means == here.
is my notes wrong?
my note says the object class has aclone() method but it has an empty implementation,
and an object of the object class is not allowed to invoke this method because of this reason.
Can someone please explain this b etter? I think I misunderstanding something

== compares object reference - are they the exact same memory reference. equals is a method implemented per class, typically to do more useful comparison (like if two strings contain the same characters, or if two lists contain the same content).
However, the default implementation in Object simply falls back to doing an == comparison, so for instances of that class, there is no difference.

== checks object identity in the context of object references.
Foo f1 = new Foo();
Foo f2 = f1; // Both f1 and f2 refer to the same object.
// f1 == f2 returns true
Foo f3 = new Foo(); // A second instance of Foo is created
// f1 == f3 returns false
Only in the context of primitive data types (boolean, byte, short, int, long, char, float and double) == checks for value.1
The equals method is nothing more than a method to enable objects to compare themselves with other objects. The documentation of equals sets requirements to how the programmer should implement the method, but technically the programmer could do anything he wants.
The implementation of Object.equals(Object) is simply return this == obj).
The equals method should never rely on nor call hashCode(), since it's possible that two objects which are considered unequal according to equals could have the same hash code. The only requirement of hashCode is the other way around: that it must return the same hash code for all object considered equal by means of the equals method.
1 As Andreas already mentioned in the comments – technically == always checks value. This also counts for object references, since object references themselves are values.

Related

How == returns false even though two Strings s1 and s3 having same hashcode? [duplicate]

This question already has answers here:
two unequal objects with same hashcode
(9 answers)
Closed 6 years ago.
public static void main(String[] args) {
String str1 = "java";
String str2 = str1.intern();
String str3 = new String(str1.intern());
System.out.println("hash1=" + str1.hashCode());
System.out.println("hash2=" + str2.hashCode());
System.out.println("hash3=" + str3.hashCode());
System.out.println("str1==str2==>>" + (str1 == str2));
System.out.println("str1==str3==>>" + (str1 == str3));
}
============================================output===>
hash1=3254818
hash2=3254818
hash3=3254818
str1==str2==>>true
str1==str3==>>false
=================================
Can anyone explain how == returns false even though s1 and s3 having same hashcode?
Despite the comments above, I suspect that you already understand that == determines if two references point to the same object (or are both null), and that you should use equals() if you want to compare two strings for data-equality.
Rather, I think what you're missing is that the hashCode() method corresponds to the equals() method in this respect; it's based on the data in an object, and in fact, it's specified that classes should always implement hashCode() in such a way that if a.equals(b), then a.hashCode() == b.hashCode(). (Of course, there's nothing in the language that enforces this.) The analogue of == that you're looking for is the System.identityHashCode() method.
However, even there it should be noted that System.identityHashCode() does not guarantee that distinct instances will have distinct identity hash codes. (It can't, because it's possible to have more than 232 objects in a JVM at the same time . . . granted, not all JVMs support that; but nothing in the Java language specification forbids it.)
In a correct implementation of equals and hashCode you have the following implications for two objects a and b (that are not null):
if a == b then also a.equals(b)
if a.equals(b) then also a.hashCode() == b.hashCode()
Both implications cannot be reversed in general.
For two Objects the == operator compares their pointer reference. So unless they are actually the exact same object it's never true.
When you do:
String a = "xyz"
while creating the string, the JVM searches in the pool of strings if there already exists a string value xyz, if so 'a' will simply be a reference of that string and no new String object is created.
But if you say:
String a = new String("xyz")
you force JVM to create a new String reference, even if "xyz" is in its pool.
and == compares the references. That's why you are getting the false result.

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.

What does the word "equals" mean in Java API?

I'm not sure anyone will know the answer to this question, unless you are responsible for writing the Jave API, but when the Java API says "equals", does it always mean that a.equals(b) evaluates to true, or sometime does it mean a == b is true? I have recently extended a class and wondered if I needed to override a method depending on where or not it used == or .equals. Specifically, I extended javafx.beans.binding.ObjectExpression and was curious about the .isEqualTo(Object other) method. I checked the source (here) and found that this method uses .equals for comparison. I'm curious if I can be confident that when I read things like
"Creates a new BooleanExpression that holds true if this ObjectExpression is equal to a constant value."
that the method is not using the == operator. Although, as I think of it, the API can't possibly mean .equals either, since (for example)
String constant = "constant";
ObjectExpress<String> stringExpression = new MyStringExpression("constant");
constant.equals(stringExpression)
will always evaluates to false. So maybe my question should be "when the API says 'equals', does it always refer to the most reasonable way to apply .equal or sometime does it refer to the analogous way to apply ==?"
EDIT
I think based on the answers I should clarify: this is not a question about the difference between == and .equal. It is about to which the Java API is referring when it uses the English word "equals".
It's clear that you do understand the difference between equals() and ==. So your question is rather philosophical :)
Generally, many APIs use "equals to" in the meaning of equals() and "is the same as" in the meaning of ==. E.g. JUnit has assertion method assertEquals() and assertSame().
However, use your common sense and analyze the language of the doucmentation. Notice in your quoted sentence from API the usage of the indefinite article:
"Creates a new BooleanExpression that holds true if this
ObjectExpression is equal to a constant value."
"a constant value" clearly means any constant value, not the same value as the "constant" value. So it is clear that this cannot mean the same as constant.equals(stringExpression).
So take it in this way: when documentation says "equals", take it that it relates to the content of the variable, not to its reference. But use common sense and read the sentence as a whole :)
Does it answer your question? :P
does it always mean that a.equals(b) evaluates to true, or sometime
does it mean a == b is true?
when the API says 'equals', does it always refer to the most
reasonable way to apply .equal or sometime does it refer to the
analogous way to apply ==?"
It's about overriding equals() method, In java, only += operator overloaded, other operators can't be overloaded means, you can't override ==
When writing an API-doc when using the term "equal" this should usually mean "equal in terms of the equals()-method". If it really does depends on the thoroughness of the writer of the documentation, but in the official API-docs I would always take as having this meaning.
For your question "can it also mean ==": it can in the way that Object's equals()-method just checks for reference-identity, that is it checks using ==.
If you use .equals it will compare the value. By using == you are comparing the reference and these doesn't have to be the same even if your values are the same.
See following website for a full explanation: http://www.javabeat.net/what-is-difference-between-equals-and/
I've copied a part of his example:
s1 = new String("abc");
s2 = new String("abc");
Now, if you use the equals() method to check for their equivalence as
if(s1.equals(s2))
System.out.println("s1.equals(s2) is TRUE");
else
System.out.println("s1.equals(s2) is FALSE");
You will get the output as TRUE as the equals() method check for the content equality.
Lets check the == operator..
if(s1==s2)
System.out.printlln("s1==s2 is TRUE");
else
System.out.println("s1==s2 is FALSE");
Now you will get the FALSE as output because both s1 and s2 are pointing to two different objects even though both of them share the same string content. It is because of new String() everytime a new object is created.
When some one creates a java class it inherit boolean equals(Object o) method from class 'Object', as all user defined class when not extending any other class extends class Object implicitly.
When this class is instantiated using new operator the equality of this objects are achieved by using this underline formula.
return (this == obj);
Hence it will return true if and only if both object refers to the same object on the heap i.e (a == b) = true
class Abc{}
Abc a = new Abc();
Abc b = a;
a==b //(true)
a.equals(b) //(true)
And suppose they are instance of same class but are two different object than
class Abc{}
Abc a = new Abc();
Abc b = new Abc();
a==b; //(false)
a.equals(b); //(false)
But when an class created overrides this equals method then this equality is evaluated using the new formula provided while overriding it. for example .equals object override by java.util.Date
public boolean equals(Object obj) {
return obj instanceof Date && getTime() == ((Date) obj).getTime();
}
This will return true if and only both Date object have equal value returned by getTime() method.
Hope this helps. Feel free to ask further questions if any doubt.

Difference in string comparison result b/w == and String#replace with == [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
String comparison and String interning in Java
I have small doubt regarding String comparisons in Java, consider the following code:
if("String".replace('t','T') == "String".replace('t','T')) {
System.out.println("true");
}
else {
System.out.println("false");
}
The above code always print's false, where as if I try like this:
if("STring" == "STring") {
System.out.println("true");
}
else {
System.out.println("false");
}
It will always print me true. Yes, I know String comparisons should be done with String.equals() or equalsIgnoreCase() method. But this is one of the question was asked in interview and I am confused. Can anyone guide me on this behavior?
As per my knowledge, in code snippet 1, "String.replace('t','T') is returning object, so object comparisons returns in false. Am I right?
"String.replace('t','T') is returning object, so object comparisons
returns in false. Am I right?
Yes, as for this case, you are right. String#replace(or any method of String class for that matter), will return a new String object (You can guess why? Immutability). And thus you would have to do the comparison using equals method, to compare their contents.
Now, in the second case: -
"STring" == "STring"
You are comparing two string literals. Now, since String literals are interned in Java, so both the literals are same (in the sense, they point to the same memory location), and hence == comparison gives you true.
The difference in comparison using == and equals is that, == compares the reference value - i.e value of memory location of objects, which will be different for two different string objects, as you are having in first case. Whereas, equals compares the actual content in those objects.
"String.replace('t','T') is returning object, so object comparisons
returns in false. Am I right?
Yes, == compares object references, and your first code is comparing two different objects.
As far as the second code is concerned its due to string interning.
ok lets do it like this, your both String objects "String" are referering to the same object.
So they are "basicly" equal. That is a thing the compiler does for you
but the method replace, does create and return a new String object, and that is why your second code is not equal.
Java always compares the basic types (int, byte, etc) or references for objects when using ==.
The java compiler optimizes the two string constants you entered to use the same object, thus the same reference, thus the == return true
DO this way
("String".replace('t','T').Tostring() == ("String".replace('t','T')).ToString()
This will solve your problem because the replace statement should be converted to string before eveluation.
You can also user the String.Equals for this or better you use ignore case as you mention in your question.
Try this:
if(string1.equals(string2)){
...
}

java: comparing classes with == or .equals(): is there a difference? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Does Java guarantee that Object.getClass() == Object.getClass()?
I know you're supposed to use equals() in general, but is there any way two Class<?> objects could be equal with equals() but not equal with ==?
edit: I am specifically looking to find out whether two class objects exist such that
Class<?> cl1 = ...
Class<?> cl2 = ...
cl1.equals(cl2) -> true
cl1 == cl2 -> false
This does not seemed to be covered by the possible duplicate question. (which is closely related)
Also it may not be true that the class objects were obtained by someObject.getClass() -- it could be that one was the result of Class.forName(...) and the other from some series of reflective actions like Method.getReturnType().
All objects have both identity (the object's location in memory) and state (the object's data). The == operator always compares identity. The default implementation of equals compares identity as well.
For a fuller explanation:
http://www.javapractices.com/topic/TopicAction.do?Id=17

Categories

Resources