引用类型变量本身无需手动初始化,真正需初始化的是其所指向的对象;成员变量默认为null,局部变量必须显式初始化,否则编译报错。

引用类型变量本身不需要手动初始化,真正需要初始化的是它所指向的对象。
引用变量和对象是两回事
Java中,引用变量就像一张“纸条”,只存着地址;而对象才是实际放在堆内存里的“东西”。声明一个引用变量,只是准备了一张空白纸条,并没在堆里造出任何东西。
- String s; —— 只是声明了一个叫 s 的引用,还没让它指向任何对象,此时 s 的值是 null
- String s = "hello"; —— 这时字符串对象被创建在堆中,“hello”有了实际内存空间,s 这张纸条才写下它的地址
- String s = null; —— 明确写上 null,和不赋值效果一样(成员变量默认就是 null),但依然没创建对象
为什么不能直接用未初始化的引用?
因为调用方法或访问字段时,JVM 要顺着地址去找对象。如果引用是 null,就等于拿着一张写着“空地址”的纸条去敲门——结果只能抛 NullPointerException。
- s.length() → s 是 null → 找不到对象 → 运行时报错
- new 出来的对象才有真实内存布局,才能响应方法调用、存储字段数据
- null 引用没有关联任何实例,也就没有
this、没有字段内存、没有虚函数表
成员变量 vs 局部变量:初始化责任不同
成员变量由 JVM 在类加载的“准备”和“初始化”阶段自动设为 null(引用类型)或 0(基本类型),所以可不写初始化语句;局部变量则完全由程序员负责,编译器强制要求使用前必须显式赋值。
- 成员变量存在类结构里,生命周期长,JVM 统一兜底
- 局部变量存在栈帧中,复用频繁,逐个初始化开销大,且容易掩盖逻辑缺陷,所以编译器直接拦截未初始化使用
- 形参本质也是局部变量,传入时已绑定实参对象,所以天然“已初始化”
数组是典型引用类型,更能说明问题
声明 String[] arr; 只建了个引用;arr = new String[3]; 才在堆里划出一块能存 3 个引用的空间(每个元素默认为 null);arr[0] = "a"; 才让第一个槽位指向真正的字符串对象。
- 没执行
new就访问arr.length→ NullPointerException - 执行了
new但没给元素赋值,arr[0].length()仍会空指针 - 数组对象本身要初始化(分配内存),数组元素是否要再初始化,取决于业务逻辑

















