核心方法
主要有以下几种方法,我会按推荐顺序和使用场景进行说明:

String.valueOf(Object obj)- 最常用、最推荐的方法Object.toString()- 面向对象设计中的标准方法"" + obj(字符串连接) - 简单但可能隐藏问题String.format()或PrintWriter.println()- 格式化输出
String.valueOf(Object obj) - 最推荐
这是将任意对象转换为字符串最直接、最安全的方法。
工作原理
String.valueOf() 方法内部会检查传入的 obj 是否为 null。
obj是null,它会返回字符串"null"。obj不是null,它会调用obj.toString()方法来获取字符串表示。
代码示例
public class ValueOfExample {
public static void main(String[] args) {
// 1. 普通对象
Person person = new Person("Alice", 30);
String personStr = String.valueOf(person);
System.out.println("Person object as string: " + personStr);
// 输出: Person object as string: com.example.Person@15db9742 (默认的toString输出)
// 2. null 对象
Object nullObj = null;
String nullStr = String.valueOf(nullObj);
System.out.println("Null object as string: " + nullStr);
// 输出: Null object as string: null (注意:这里输出的是字符串"null",而不是null)
}
}
// 一个简单的Person类,没有重写toString()
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// ... getters and setters
}
优点
- 安全处理 null:能优雅地处理
null值,避免NullPointerException。 - 简单直接:代码意图清晰,一看就知道是要把对象转成字符串。
Object.toString()
这是 Java 中所有对象都具备的方法,因为它是 Object 类的成员,当你打印一个对象时(例如使用 System.out.println(obj)),JVM 内部会自动调用这个方法。
工作原理
Object类提供的默认toString()方法会返回一个字符串,格式为:"类的全限定名@对象的哈希码",com.example.Person@15db9742。- 这个默认值通常对我们没有太大用处。最佳实践是在你自定义的类中重写(Override)这个方法,以返回一个对对象内容有意义的描述。
代码示例
不重写 toString() (使用默认行为)

Person person = new Person("Bob", 25);
System.out.println(person.toString());
// 输出: com.example.Person@7852e922 (和上面一样)
重写 toString() (推荐做法)
// 修改 Person 类,重写 toString()
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override // 注解,表示重写父类方法
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
// 在 main 方法中测试
Person person = new Person("Charlie", 40);
System.out.println(person.toString());
// 输出: Person{name='Charlie', age=40}
// 即使不显式调用 toString(), System.out.println 也会自动调用
System.out.println(person);
// 输出: Person{name='Charlie', age=40}
优点
- 面向对象:符合 Java 的设计哲学,对象应该能自我描述。
- 可读性好:重写后可以提供非常有用的调试和日志信息。
缺点
- 对 null 不安全:如果直接对一个
null对象调用toString(),会抛出NullPointerException。Object obj = null; obj.toString(); // 抛出 NullPointerException
"" + obj (字符串连接)
这是一种非常简洁的语法糖,在代码中很常见。
工作原理
当 Java 遇到 String + Object 的操作时,编译器会自动将其转换为 new StringBuilder().append("").append(obj).toString(),这个 append 方法的内部逻辑和 String.valueOf() 是一样的。
代码示例
Person person = new Person("David", 35);
String personStr = "" + person;
System.out.println(personStr);
// 输出: Person{name='David', age=35} (前提是Person类重写了toString())
Object nullObj = null;
String nullStr = "" + nullObj;
System.out.println(nullStr);
// 输出: null (同样能安全处理null)
优点
- 代码简洁:输入量少,看起来干净。
- 能处理 null:和
String.valueOf()一样安全。
缺点
- 性能开销:每次使用 连接字符串,JVM 都会隐式地创建一个新的
StringBuilder对象,在循环中进行大量字符串连接时,这会带来不必要的性能开销,应优先使用StringBuilder。 - 可读性稍差:对于初学者来说,
String.valueOf(obj)的意图比"" + obj更明确。
String.format() 或 PrintWriter.println() - 格式化输出
当你需要将对象嵌入到更复杂的字符串模板中时,这些方法非常有用。

代码示例
Person person = new Person("Eve", 28);
// 使用 String.format()
String formattedStr = String.format("User Info: Name=%s, Age=%d", person.name, person.age);
System.out.println(formattedStr);
// 输出: User Info: Name=Eve, Age=28
// 使用 PrintWriter.println (例如日志场景)
import java.io.PrintWriter;
import java.io.StringWriter;
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.println("Logging entry for user: " + person); // 这里会自动调用 person.toString()
pw.close();
System.out.println(sw.toString());
// 输出: Logging entry for user: Person{name='Eve', age=28}
总结与最佳实践
| 方法 | 示例 | 优点 | 缺点 | 推荐场景 |
|---|---|---|---|---|
String.valueOf() |
String.valueOf(obj) |
安全、清晰、标准 | 无明显缺点 | 绝大多数场景下的首选,尤其是在处理可能为 null 的对象时。 |
Object.toString() |
obj.toString() |
符合OOP设计,可自定义输出 | 对 null 不安全 |
在你自己定义的类中,总是重写它,在确定对象不为 null 时使用。 |
"" + obj |
"" + obj |
简洁、能处理 null |
循环中性能较差 | 代码行数要求极简的场景,但要注意性能问题。 |
String.format() |
String.format(...) |
功能强大,格式化灵活 | 语法稍复杂 | 需要将对象信息嵌入到特定格式模板中时。 |
最终建议
-
对于你自己写的类:总是重写
toString()方法,这会极大地方便你的调试、日志记录和任何需要对象字符串表示的场景。 -
在需要将任意对象(可能是
null)转换为字符串时:优先使用String.valueOf(obj),这是最健壮、最不容易出错的选择。 -
在日志或打印输出时:直接传入对象即可,
logger.info(myObject)或System.out.println(myObject),框架会自动调用toString(),如果类重写了toString(),输出会非常有用。 -
避免在循环中使用
"" + obj,改用StringBuilder。
