Why sometimes the relationship operator "==" cannot be used instead of the .equals () method to compare objects?

I looked at it in a book, which is usually more thorough in terms of explanations than a website.

Take this for an example:

if (nickname == "Bob") 

The condition will be true only if nickname refers to the same String object.

Here is a sentence that I was confused, can someone explain why this is so:

For efficiency, Java creates only one string object for each string constant.

The book states that the method of assembling the "Bob" object also affects whether this condition is incorrect , which confuses me the most.

For example:

 String nickname = "Bob"; ... if (nickname == "Bob") //TRUE 

But if "Bob" is created from the .substring() method, the condition will be FALSE.

 String name = "Robert"; String nickname = name.substring(0,3); ... if (nickname == "Rob")//FALSE 

Why is this so?

Edit: at the end of the bookโ€™s explanation, I found a sentence that also confuses me:

Since string objects are always created by the compiler, you never have an interest in sharing two strings.

Isn't everything we write created by the compiler?

+7
java object
source share
3 answers

You need to understand 2 things

one)

 String a = "Bob"; String b = "Bob"; System.out.println(a.equals(b)); System.out.println(a == b); 

What do you think? What result?

 true true 

What does it do? The first row created in the row pool in the constant generation memory. The second line gets the existing object from the pool.

 String a = "Bob"; // create object in string pool(perm-gen) String b = "Bob"; // getting existing object. 

How correctly did you notice:

For efficiency, Java creates only one string object for each string constant.

2)

 String nickname = name.substring(0,3); 

Since String is an immutable object name.substring(0,3); created by new String("Rob") in heap memory , not perm-gen.

Note:

In Java 8, a row pool is created in the PermGen heap area, garbage collection can occur in Perm space, but depends on the JVM and JVM. By the way, from the JDK 1.7 update, the row pool moves to the heap area where the objects are created.

More details here .

+10
source share

String literals are internally processed by the JVM, so for each unique string literal, it always refers to the same object if it has the same value. For example, the string literal "test" in class A will be the same object as the string literal "test" in class B.

Isn't everything we write built by the compiler?

The compiler simply adds the string literal to the constant pool classes at compilation and loads it with a special command called LDC , the rest is processed by the JVM, which loads the string constant from a special pool of constant strings which never removes / garbage, does not collect any objects (previously permgen )

However, you can get the "internal" version of any string (as if it were a string literal) using String#internal() , which would make the == operator work again.

+2
source share

This is about objects.

Since these are not primitives, == does not compare what they are. == compares where they are (in the heap memory).

.equals() should (if implemented) compare what is contained in this memory.

This is a part that is easily forgotten, because small lines and numbers in a box often do not receive new memory when creating, because it is more optimal, instead it indicates a cached version of the same. Thus, you can again and again ask for a new โ€œBobโ€ and simply pass the link (memory address) to the same โ€œBobโ€. This makes us compare them as primitives, since it looks like the same thing. But not every object will have this happen to him, so it is a bad habit to allow yourself to develop.

This trick only works if 1) the corresponding object already exists, 2) it is immutable, so you cannot surprise users with other โ€œcopiesโ€ by changing it.

To abuse the old metaphor, if two people have the same address, itโ€™s safe to bet that they keep the same things at home, as this is the same house. However, just because two people have different addresses, this does not mean that they do not support the same things at home.

The implementation of .equals() is to determine what we care about when comparing what is stored in these objects.

So only trust == to compare primitive values. Use .equals() to ask the object what it believes it is equal to.

Also, this is not just a problem with Java. Each object-oriented language that allows you to directly process primitives and object references / pointers / memory addresses will force you to deal with them differently because the object reference is not an object that it is.

Objects The value does not match the identifier . If there was only one copy of the object with the same contents. Since language cannot fully do this, you are stuck dealing with these two concepts in different ways.

+1
source share

All Articles