为什么 Java 中打印Object类型的变量无需强转,而从Object类型的数组中取元素却要强转?

两个奇怪的现象

case1:打印Object对象时,无需强转:

Object val = 25;
System.out.println(val); // 直接打印,输出:25
// 不需要:(String)val 或 (Integer)val

case2:当我们要使用Object 数组中的元素时,需要强转

class Node{
    int val;
    Node next;
    Node(int val){
        this.val = val;
    }
}
Object[] pair = new Object[]{23, new Node(5)};
int sum = (Integer) pair[0] + 10;     // 必须强转
Node node = (Node) pair[1];  					// 必须强转
// 不能直接:Node node = pair[1];

对于 case2,当我们不强转的话,编辑器会提示如下错误:

int sum = pair[0] + 10;     // 报错:运算符 '+' 不能应用于 'java. lang. Object'、'int'
Node node = pair[1];  			// 报错:需要的类型:Node 提供的类型:Object

背后的原因

case1不需要强转是因为在调用print语句时,底层实际上已经做了以下操作:

System.out.println(val);
				↓
public void println(Object obj) {
    print(String.valueOf(obj));
}
				↓
public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

可以看到,在调用 print 语句时,会把 Object 类型转换为 String 类型,然后调用这个对象的 toString()方法,(这也就是为什么我们通常需要重写 toString()的原因)

打印方法内部已经帮我们做了类型转换,所以不再需要我们手动强转

那么 case2 为什么不使用强转会报错呢?

由于 java 有编译时类型、运行时类型,前者表示变量在代码中声明时的类型,后者表示变量在程序运行时实际指向的类型

而编译器只能够看到编译时类型,并且由于编译器需要确保类型安全,所以就要阻止类型不匹配的运算

那么 case2 为什么使用了强转就不会报错呢

这是因为,当我们使用强转,就等于告诉编译器,这些变量在运行时是某某类型,由开发者来保证在运行时的类型和强转的类型一致,因此编译器就会根据用户强转后的类型来进行类型检查。

posted @ 2025-10-06 20:29  陈一i  阅读(4)  评论(0)    收藏  举报