Search code examples
javastringreferencetostringhashcode

After override hashCode, toString() return the same value for the same object but after using "==" return false


As you may know Object has some function, For example we have toString() from oracle Documentacion we can know by default it's return HexValue of hashCode() https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#toString() We also can use hashCode() for checking of equality object (of course implementation depends on you) So I made implementation for my Class Projekt :

public class Projekt {

    int i;
    public Projekt(int i) {
        this.i=i;
        // TODO Auto-generated constructor stub
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + i;
        return result;
    }   
}

Test Code:

Projekt projekt = new Projekt(1);
System.out.println(projekt.toString());
System.out.println(projekt.toString() == projekt.toString());

Output:

Projekt@20
false

Also i try to inside value from projekt.toString() in StringPool by writing:

    String string = projekt.toString();
    String stringABC = projekt.toString();
    System.out.println(string == stringABC);

According to PoolString i should have the same reference but outPrint is false.

So this method return different reference value but i can't understand why?


Solution

  • From your comment:

    I copied this from diffrent comenatry: But to save memory we're using StringPool. If we have the same value, refereance is also the same it's working just for creating String not by constructor. If i had String s = new String("a"); String s2 = new String("a"); I used 2 space in memory, but when i use String s = "a"; String s2 = "a" I use 1 space in memory. So that's mean toString() return "new String()"?

    Your source should have said:

    ...it's working just for creating String using string literals.

    That way it might have been clearer, because there are many ways to create new String objects without directly calling the constructor. String literals are those things surrounded by " (including the quotes), such as "a" or "b" or "Welcome to Stack Overflow".

    Only string literals1 are pooled automatically. You can manually put a string into the pool by calling intern().

    When you concatenate two strings (e.g. stringA + stringB), a new string is generally created, as described here.

    Now let's look at what Object.toString does:

    The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of:

    getClass().getName() + '@' + Integer.toHexString(hashCode())
    

    Note that strings are being concatenated here, so a new string object is being created here, hence the output.

    And to answer the question of:

    So that's mean toString() return "new String()"?

    Yes, but not directly. The compiler will turn the + operators in Object.toString into some code using StringBuilder (or rather, "the compiler has turned..." since the Object class has already been compiled). At the end, it will call StringBuilder.toString, and that will create a new String object.


    1Constant expressions of strings, to be more accurate.