Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Understanding Equality, on page 118 (Java OCA 8 Programmer I Study Guide)

 
Mushfiq Mammadov
Ranch Hand
Posts: 187
25
Java jQuery Netbeans IDE
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
On page 118, the last example:
Maybe authors intended to write System.out.println(t1 == t3); on line 7.

I want to specify one point regarding paragraph above example that I understand correct or not.
..If a class doesn’t have an equals method, Java determines whether the references point to the same object – which is exactly what == does. In case you are wondering, the authors of StringBuilder did not implement equals(). If you call equals() on two StringBuilder instances, it will check reference equality.

According this I understand that the result of == and equals() are always the same for two StringBuilder instances, unlike String. Am I correct or not?

The another point, on page 105, The String Pool section, second paragraph:
The string pool contains literal values that appear in your program. For example, “name” is a literal and therefore goes into the string pool. myObject.toString() is a string but not a literal, so it does not go into the string pool. Strings not in the string pool are garbage collected just like any other object.

My question is that
s1 and s2 are kept in the string pool or not?
 
Liutauras Vilda
Bartender
Pie
Posts: 2793
112
BSD VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Maybe authors intended to write System.out.println(t1 == t3); on line 7.
I'm not sure what authors intended to be there, but in both cases it is "true". Because t1 == t1 comparing the same reference variable with itself, so it is "true". t1 == t3 is also "true", because "Tiger t3 = t1;" (t1 object reference being assigned to t3 reference variable, so these two references refers to the same object.
 
Liutauras Vilda
Bartender
Pie
Posts: 2793
112
BSD VI Editor
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
According this I understand that the result of == and equals() are always the same for two StringBuilder instances, unlike String. Am I correct or not?
Yes, you're correct. It is like this, because StringBuilder class is inherited from Object class, which is the superclass (or base class) of all classes in Java, and this inherited method compares references equality. So it gives you always "false" unless you supply the same reference variables as arguments. String class overwrite this "equals" method, so it gives different results.
 
Tim Cooke
Sheriff
Pie
Posts: 3209
142
Clojure IntelliJ IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
When it comes to comparing Strings of any kind all you need to remember is always always always use .equals(), and never never never use ==.
 
Roel De Nijs
Sheriff
Posts: 10662
144
AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Mushfiq Mammadov wrote:Maybe authors intended to write System.out.println(t1 == t3); on line 7.

Probably yes. But based on the provided code, only the authors really know (as there's nothing wrong with the current code and the output ).

Mushfiq Mammadov wrote:According this I understand that the result of == and equals() are always the same for two StringBuilder instances, unlike String. Am I correct or not?

You are absolutely correct! Here is the equals method of ObjectSo if a class doesn't override the equals method (like StringBuilder), using equals and == will be the same. But it's not exactly the same, there are few gotcha's:
  • imagine the "this" object is null -> invoking the equals method will throw a NullPointerException, the == operator will return true or false
  • with == operator you could get an "incompatible types" compiler error, will never happen when using the equals method. Illustrated in this code snippet



  • Mushfiq Mammadov wrote:s1 and s2 are kept in the string pool or not?

    First of all, s1 and s2 will never be in the string pool, because these are reference variables; only the String objects will exist in the pool (and each object has a pool reference variable which is returned if you have a string which is already in the pool).

    Secondly, your example is a bit tricky because "string" and "Hello World" are String literals and therefor will be definitely in the pool. But the String objects created by o.toString() and "Hello World".trim() are not String literals and thus will not be in the String literal pool. Let's add another (hopefully more clear) example. In the above code, " Hello World " will be in the String literal pool because it's a string literal "Hello World" (the result of invoking the trim method on s10) will not be in the String literel pool, because it's not a literal.

    Finally, you should definitely read (and/or maybe re-read) this excellent article about string literals and the string literal pool.

    Hope it helps!
    Kind regards,
    Roel
     
    Jeanne Boyarsky
    author & internet detective
    Marshal
    Posts: 35279
    384
    Eclipse IDE Java VI Editor
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Mushfiq Mammadov wrote:Maybe authors intended to write System.out.println(t1 == t3); on line 7.

    Yes. As noted what we typed wasn't wrong, but it wasn't as meaningful as t1 == t3.
     
    Mushfiq Mammadov
    Ranch Hand
    Posts: 187
    25
    Java jQuery Netbeans IDE
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thanks all for your reply

    Roel De Nijs wrote:Secondly, your example is a bit tricky because "string" and "Hello World" are String literals and therefor will be definitely in the pool. But the String objects created by o.toString() and "Hello World".trim() are not String literals and thus will not be in the String literal pool.

    I am confused one point. I read from book
    Strings are immutable and literals are pooled. The JVM created only one literal in memory. x and y both point to the same location in memory; therefore, the statement outputs true.

    We specify that "Hello World" is literal and "Hello World".trim() is not String literal. But we compare these the result will be true
    According this x and z both point to the same location in memory. Which thing I don't understand correctly?
     
    Roel De Nijs
    Sheriff
    Posts: 10662
    144
    AngularJS Chrome Eclipse IDE Hibernate Java jQuery MySQL Database Spring Tomcat Server
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Mushfiq Mammadov wrote:According this x and z both point to the same location in memory. Which thing I don't understand correctly?

    That's an excellent question Have a well-deserved cow!

    Now let's see if I can provide an excellent answer as well.

    Let's start with a much easier example, using the toString methodThis code snippet prints true as well. Why? Because of the implementation of the toString methodSo "Hello World" is in the String pool and is referred by (just for educational purpose) reference variable pool1. So x is equal to pool1 (because "Hello World" is a String literal and is in the pool, so x and pool1 point to the same location in memory). Then you invoke the toString method on pool1 (because "Hello World" is a String literal and in the String literal pool and thus referenced by pool1). And the toString method just returns this (the special reference variable to the current object), and because the toString method is invoked on pool1, pool1 is returned. So z and pool1 point to the same location in memory as well, therefore x==z evaluates to true.

    Now back to your example (with the trim method)The reason why this code prints true as well, is because of the implementation of the trim method. I don't want to bother you with the details of this method, so just have a look at the javadoc of this method:
    javadoc trim() method wrote:Returns: A copy of this string with leading and trailing white space removed, or this string if it has no leading or trailing white space.
    So "Hello World" has no leadin or trailing white space, thus this string is returned. That's completely similar with the toString method and thus explains why true is printed as well.

    And now finally a code snippet that should illustrate all the above:So that's exacty as expected: "Hello World" (referenced by variable x) and " Hello World " (with leading and trailing space, referenced by variable y) are 2 String literals which are not the same nor are both strings equal. Then you trim the string referenced by variable y, which results in a "Hello World" string (referenced by variable z). Although this String is equal to the string literal "Hello World" (referenced by variable x), the string referenced by variable z is not a String literal and thus not the same as the string literal "Hello World" (referenced by variable x).

    Hope it helps!
    Kind regards,
    Roel
     
    Mushfiq Mammadov
    Ranch Hand
    Posts: 187
    25
    Java jQuery Netbeans IDE
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Roel De Nijs wrote:
    javadoc trim() method wrote:Returns: A copy of this string with leading and trailing white space removed, or this string if it has no leading or trailing white space.

    Perfect explanation! Thanks a lot, Roel

    Roel De Nijs wrote:That's an excellent question Have a well-deserved cow!

    Thanks
     
    • Post Reply
    • Bookmark Topic Watch Topic
    • New Topic