You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何调用方法获取的sb引用值不为null而是赋值前的内容?

为什么StringBuilder引用在方法内赋值为null后,外部仍然保留原有状态?

这是个非常经典的Java参数传递问题,核心在于搞清楚Java里的值传递到底是怎么回事,尤其是对象类型的参数传递逻辑。咱们一步步拆解你的代码,就能明白为什么会出现这种情况:

首先先看你的完整代码:

public class Test{
    void testRefs(String str, StringBuilder sb){
        str = str + sb.toString();
        sb.append(str);
        System.out.println(sb);
        str = null;
        sb = null;
        System.out.println(sb);
    }
    public static void main(String[] args){
        String s = "aaa";
        StringBuilder sb = new StringBuilder("bbb");
        new Test().testRefs(s, sb);
        System.out.println("s="+s+" sb="+sb);
    }
}

关键原理:Java的参数传递是值传递

很多人会误以为Java的对象是引用传递,但实际上Java只有值传递:

  • 对于基本类型,传递的是变量的值的副本;
  • 对于对象类型,传递的是对象引用的副本——也就是说,方法里的sb参数和main方法里的sb变量,是两个独立的变量,但它们一开始指向同一个StringBuilder对象。

逐行分析代码执行流程

  1. main方法初始化:

    String s = "aaa";
    StringBuilder sb = new StringBuilder("bbb");
    

    这里sb变量指向一个内容为"bbb"的StringBuilder对象。

  2. 调用testRefs(s, sb):
    此时Java会把main里s的引用副本、sb的引用副本,分别传递给方法的参数str和sb。现在:

    • main.sb 和 testRefs.sb 指向同一个StringBuilder对象;
    • main.s 和 testRefs.str 指向同一个String对象"aaa"。
  3. 执行str = str + sb.toString();:
    String是不可变类型,str + sb.toString()会创建一个新的String对象"aaabbb",然后方法内的str变量会指向这个新对象——但这和main里的s变量没有任何关系,因为main.s仍然指向原来的"aaa"。

  4. 执行sb.append(str);:
    方法内的sb副本指向的是和main.sb同一个StringBuilder对象,所以append操作会直接修改这个对象的内容,变成"bbb" + "aaabbb" = "bbbaaabbb"。这时候main里的sb对象也会看到这个变化,因为它们指向的是同一个实例。

  5. 执行str = null; sb = null;:
    这一步只是把方法内的两个局部变量(引用副本)赋值为null,让它们不再指向原来的对象。但main里的sb变量仍然牢牢指向那个已经被修改过的StringBuilder对象,所以这一步对外部完全没有影响。

  6. 方法内的两次输出:

    • 第一次System.out.println(sb);输出的是修改后的对象内容bbbaaabbb;
    • 第二次System.out.println(sb);输出null,因为此时方法内的sb已经被赋值为null了。
  7. 回到main方法的输出:
    System.out.println("s="+s+" sb="+sb); 会输出 s=aaa sb=bbbaaabbb,原因是:

    • s还是"aaa",因为方法内的str修改的是引用副本指向的新对象,和原变量无关;
    • sb是修改后的"bbbaaabbb",因为之前的append操作修改了对象本身,而方法内的sb=null只是修改了副本引用,没有影响原对象。

总结一下核心要点

  • 如果在方法内修改参数指向的对象的内容(比如StringBuilder.append),外部会看到变化,因为参数和外部变量指向同一个对象;
  • 如果直接给参数变量赋值(比如sb=null),只是让方法内的副本变量不再指向原对象,外部变量不受任何影响——这就是你疑惑的根本原因。

内容的提问来源于stack exchange,提问作者Michael

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:16:23