Doubts about the toString() method of the Object class

Asked

Viewed 6,312 times

18

I’ve been doing some tests with the method toString() class java.lang.Object and found that the obtained result changes with each execution, as the example below:

Excerpt from the tested code

public class Teste {
    public static void main(String[] args) {
        NovaClasse NC = new NovaClasse();
        System.out.println(NC.toString());
    } 
}

Outputs obtained

NovaClasse@1f1fba0
NovaClasse@1befab0
NovaClasse@13c5982

I found that the method toString() returns the name of the class to which the object belongs + @ + 7 hexadecimal characters that I first thought referred to the memory address in which the object was stored, but it seems that they are a hashCode.

Doubts

What is and what is the use of this hashCode? Why its value varies from one run to another if my code remains the same?

2 answers

22


According to the own documentation of the Object class, the method toString() returns a String representation of the object.

Looking at the code, the implementation of the method toString() we see:

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

What is still a representation of the object, however, is a representation that does not serve us much, because the information returned has no value for us users.

The method toString() becomes valuable when we overwrite it by making it return what we consider relevant to the object.

Example:

class Pessoa {
    private String nome;
    private int idade;

    public Pessoa(String nome, int idade) {
        this.nome = nome;
        this.idade = idade;
    }
    public String getNome() { return nome; }
    public void setNome(String nome) { this.nome = nome;}
    public int getIdade() { return idade; }
    public void setIdade(int idade) { this.idade = idade; }

    @Override
    public String toString() {
        return "Me chamo: " + this.getNome() + ", tenho: " + this.getIdade() + " anos.";
    }
}

public class TestePessoa {
    public static void main(String[] args){
        Pessoa pessoa = new Pessoa("Bob", 20);
        System.out.println(pessoa);
    }
}

Returns:

My name is Bob, I’m 20.

That is, we overwrite the method toString() so that the information shown by the object is interesting to us in a didactic example, rather than a hexadecimal representation of the hashCode() of the object, which we use for nothing.

EDIT

The method println() is overloaded to print numerous different types of data, in your example you used the method println(String):

System.out.println(NC.toString());

You made an explicit call to the method toString() of your object, already in my example I called the method toString() implicitly, using the overloaded version println(Object), that by definition returns a String representation of the object, i.e., it prints the return of the method toString() of your object.

EDIT2

What is and what is the use of this hashcode? Why does its value vary from one run to the other if my code remains the same?

The implementation of hashCode() in the Object class doesn’t matter much to us, according to the documentation itself:

This is typically implemented by Converting the Internal address of the Object into an integer, but this implementation technique is not required by the Javatm Programming language.

In free translation:

It is typically implemented by converting the internal address of an object into an integer, but this implementation technique is not required by the Javatm programming language.

The hashCode() is also a method that should be overwritten if we want to use consistently. It is often used to find objects inside a Collection, but I think your argument is beyond the scope of the question, so I’ll close this way.

11

I’ll disagree with Math’s answer. She’s not wrong, but he provides one himself link for documentation that tells how the method should be written, and the answer in my assessment does not do as the documentation says. I know there are those who think like him, but I think they learned from someone who did not understand the documentation and continue to do wrong.

Let’s get the documentation:

Returns a string representation of the Object. In general, the toString method Returns a string that "textually represents" this Object. The result should be a Concise but informative representation that is easy for a person to read. It is Recommended that all subclasses override this method.

Has more:

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:

It says that you should use the class name in this method. Of course giving some identity value is more useful than just the class name will have advantages. But this is the standard implementation.

Think, if one day you need to return a different text, what will you do? Change this text? What if the application depends on that specific text to do something? After all the method is engine, it can be used for anything involving representation and it should be stable, the result is part of the API contract. And if you really need to change, you’d have to create another method, it would become a mess, just because you’re mixing functions.

There is some controversy about the right conceptual use.

My understanding and many much more experienced people and with training (in the broad sense, not only of certified study) much better than me, is that this method has debugging function or at most for conversion of data to serialization or some very specific activity that has more to do with the mechanism than with the business rule.

There are those who disagree with that, and in Java there seems to be a culture of being more than that, which shows a strange culture because it’s a language that tries to do the right thing, even if it’s not always practical, but at this point, in exceptions and other things, seek the most practical even if conceptually wrong.

The method should only return the simple identity of the object. Something to indicate what this object is, what its important content is as basic as possible. If you can’t return something like this, return the class name, in case array.

If you want a formatted message, create a method to return it like this. If you want it standardized, you can even use a toString(alguma coisa) (different signature), so with a signature other than what is in every object is already something that is not done to meet the need of the mechanism.

Adorn the text of toString() was the right Integer it should be like this:

public String toString() {
     return String.format("O valor do objeto é %s", String.valueOf(value);
}

I put in the Github for future reference.

This is what you’re doing in Math’s answer class. This is very wrong. It’s not his fault, everyone does so, so everyone thinks I’m wrong. It’s a matter of interpreting the documentation.

Is this representative of the object? Is it concise? I don’t think so. Java actually encourages right, but a lot of people don’t interpret the documentation.

I would like Java to have something a little better standard to result in text with strings, at least I don’t know something. C# did this. That’s why people complain about these little Java problems. All technology that comes after one that succeeds tends to avoid certain errors of its predecessor.

But I agree that the focus of the question, about the hashcode, was well answered by Math, so I have my vote for her.

  • In fact I had never attempted to which the real meaning of the "useful information" that must be returned by toString(), in my case I used a more didactic example despite being able to induce error when implementing in a real situation. I liked your answer in what you say about the correct conceptual use has more to do with the mechanism, such as a serialization, +1

Browser other questions tagged

You are not signed in. Login or sign up in order to post.