16

If toString is not defined, then Java prints class name with some hash. How to reach this functionality if toString is defined?

package tests.java.lang;

public class Try_ToString {

    public static class MyClass {

        protected int value;

        public MyClass(int value) {
            this.value = value;
        }
    }

    public static class MyClass2 extends MyClass {
        public MyClass2(int value) {
            super(value);
        }
        @Override
        public String toString() {
            return String.valueOf(value);
        }
    }

    public static void main(String[] args) {

        MyClass a = new MyClass(12);
        MyClass b = new MyClass2(12);

        System.out.println("a = " + a.toString());
        System.out.println("b = " + b.toString());

    }
}
Suzan Cioc
  • 29,281
  • 63
  • 213
  • 385
  • 1
    I can't accept there's no simple solution without reflection but I can't find it :( – Denys Séguret May 05 '14 at 08:39
  • There is no direct way to do this in the [general case](http://stackoverflow.com/questions/15668032/how-to-call-the-overridden-method-of-superclass), but for the specific case of `tostring` and `Object` the answers below will help. – merlin2011 May 05 '14 at 08:42
  • 1
    @DmitryBychenko Not if the super class also implements toString... – assylias May 05 '14 at 08:47
  • In fact, I don't see any reasonably usable solution, even with reflection... – Denys Séguret May 05 '14 at 08:51

3 Answers3

19

The answer from @immibis is correct, however it wouldn't work if your class override the hashcode method. But you can use System.identityHashcode.

Returns the same hash code for the given object as would be returned by the default method hashCode(), whether or not the given object's class overrides hashCode(). The hash code for the null reference is zero.

public static String defaultToString(Object o) {
     return o.getClass().getName() + "@" + 
            Integer.toHexString(System.identityHashCode(o));
}
Alexis C.
  • 91,686
  • 21
  • 171
  • 177
  • 2
    The default `toString` does not use `System.identityHashCode`. – user253751 May 05 '14 at 09:46
  • 2
    @immibis By "default toString", I assumed the OP means the one you get if you don't override hashcode in your class. – Alexis C. May 05 '14 at 09:51
  • 2
    @immibis FYI, if hashcode is not overriden for the object's class, `hashcode()` calls the same method as `System.identityHashcode` to get the hash value (if you look at the native implementation (I looked for OpenJDK)). – Alexis C. May 05 '14 at 10:05
  • 1
    i assumed the OP meant the one you get if you don't override `toString` - which always uses `hashCode`, even if that does not call `System.identityHashCode`. – user253751 May 05 '14 at 10:22
  • 1
    If it's already on your classpath you might use `ObjectUtils.identityToString()` from apache commons-lang library instead of implementing it yourself. – Josef Borkovec Mar 24 '17 at 12:50
13

The default toString implementation just concatenates the object's class name, "@", and its hashCode in hexadecimal.

public static String defaultToString(Object o) {
    return o.getClass().getName() + "@" + Integer.toHexString(o.hashCode());
}
user253751
  • 57,427
  • 7
  • 48
  • 90
  • This answer provides a solution to this specific use case scenario which is why it was marked as a valid answer, however, what if there really is a case you want to access an implemenation of a method which you ovveride but still end up willing to use. How would you access the super.method()? Currently it seems Java does not support this? Would we really have to re-write the same method again for this purpose? – Barrosy Nov 25 '22 at 23:18
  • 1
    @Barrosy You can write in the class `public String defaultToString() {return super.toString();}`. If you can't edit the class, then yes you have to write what you want the computer to do, and you do not get to say things like "the default toString" because the class is a black box when viewed from the outside – user253751 Nov 27 '22 at 12:01
2

The docs tell the how the implementation works.

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())

You could just do that, or put it in a (static?) method.

Community
  • 1
  • 1
PurkkaKoodari
  • 6,703
  • 6
  • 37
  • 58