String.valueOf() vs. Object.toString()

后端 未结 10 766
挽巷
挽巷 2020-12-12 10:21

In Java, is there any difference between String.valueOf(Object) and Object.toString()? Is there a specific code convention for these?

10条回答
  •  青春惊慌失措
    2020-12-12 10:56

    Most has already been mentioned by other answers, but I just add it for completeness:

    1. Primitives don't have a .toString() as they are not an implementation of the Object-class, so only String.valueOf can be used.
    2. String.valueOf will transform a given object that is null to the String "null", whereas .toString() will throw a NullPointerException.
    3. The compiler will use String.valueOf by default when something like String s = "" + (...); is used. Which is why Object t = null; String s = "" + t; will result in the String "null", and not in a NPE. EDIT: Actually, it will use the StringBuilder.append, not String.valueOf. So ignore what I said here.

    In addition to those, here is actually a use case where String.valueOf and .toString() have different results:

    Let's say we have a generic method like this:

    public static  T test(){
      String str = "test";
      return (T) str;
    }
    

    And we'll call it with an Integer type like this: Main.test().

    When we create a String with String.valueOf it works fine:

    String s1 = String.valueOf(Main.test());
    System.out.println(s1);
    

    This will output test to STDOUT.

    With a .toString() however, it won't work:

    String s2 = (Main.test()).toString();
    System.out.println(s2);
    

    This will result in the following error:

    java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Integer

    Try it online.

    As for why, I can refer to this separated question and its answers. In short however:

    • When using .toString() it will first compile and evaluate the object, where the cast to T (which is an String to Integer cast in this case) will result in the ClassCastException.
    • When using String.valueOf it will see the generic T as Object during compilation and doesn't even care about it being an Integer. So it will cast an Object to Object (which the compiler just ignores). Then it will use String.valueOf(Object), resulting in a String as expected. So even though the String.valueOf(Object) will do a .toString() on the parameter internally, we've already skipped the cast and its treated like an Object, so we've avoided the ClassCastException that occurs with the usage of .toString().

    Just thought it was worth mentioning this additional difference between String.valueOf and .toString() here as well.

提交回复
热议问题