当前位置: 移动技术网 > IT编程>开发语言>Java > String是值传递还是引用传递

String是值传递还是引用传递

2019年10月29日  | 移动技术网IT编程  | 我要评论

tokyo hot n0664,朴寒星个人资料,人教版一年级语文下册教学计划

string中的坑

  最近看到一道关于string的面试题,差点让我以为string是值传递,就是下面这个例子,体验下:

public class demo{
    public static void main(string[] args) {
        demo d = new demo();
        string str = "bea";
        d.change(str);
        system.out.println(str);
    }
    void change(string s){
        s= s.replace('a', 'e');
        s = s.tolowercase();
    }
}

  当时一看到这个题目,我第一反应就是输出”bee“,因为string是引用类型,其参数传递的方式就是引用传递,传递的是string的地址。可是答案让我的大吃一惊,“bea”,str根本就没有发生变化!!

  难道string是值传递?难道string是基本类型?

  其实都不是,后来通过查阅相应资料发现,jvm在实例化字符串时会使用字符串常量池,把str作为参数传入change()方法。jvm复制了一份str变量,为了便于理解我们叫它str'。这个时候str和str'都指向字符串常量池中的“abc”。

  当我们执行s = s.replace('a', 'e');
其实相当于执行了s = new string(s.replace('a', 'e'));

 要理解上面这两段话,就要从java的底层结构说起了。java的内存模型大体分为 (细分还有方法区,和程序计数器等)。

1.基本类型的变量放在栈里;

2.封装类型中,对象放在堆里,对象的引用放在栈里。

java在方法传递参数时,是将变量复制一份,然后传入方法体去执行。

根据这些再细分一下jvm的执行过程

1.虚拟机在堆中开辟一块内存,并存值”bea”。

2.虚拟机在栈中分配给str一个内存,内存中存的是1中的地址。(1指第一步)

3.虚拟机复制一份str,我们叫str’,str和str’内存不同,但存的值都是1的地址。

4.将str’传入方法体

5.方法体在堆中开辟一块内存,并存值”bee”。

6.方法体在堆中再次开辟一块内存,并存值”bee”。

7.方法体将str’的值改变,存入5的内存地址。

8.方法结束,方法外打印str,由于str存的是1的地址,所有打印结果是”bea”。

 string的底层是一个不可变数据,所以每次给他赋新的值的时候都相当于新建了一个string对象(如果string常量池里没有该字符串的话),我们可以验证一下。

public class demo{
    public static void main(string[] args) {
        demo d = new demo();
        //通过比较str的hashcode来比较两个对象是否为同一对象
        string str = "bea";
        system.out.println("第一次string的hashcode:"+str.hashcode());
        str = "bee";
        system.out.println("第二次string的hashcode:"+str.hashcode());
        //stringbuilder来试一次
        stringbuilder s = new stringbuilder("bea");
        system.out.println("第一次stringbuilder的hashcode:"+s.hashcode());
        s.append('t');
        system.out.println("第二次stringbuilder的hashcode:"+s.hashcode());
        system.out.println("调用方法前的stringbuilder对象的值:"+s);
        d.change(s);
        system.out.println("调用方法后的stringbuilder对象的值:"+s);
    }
    void change(stringbuilder s){
        s = s.append('s');
    }
}

  看看执行的结果~

file

tips: hashcode并不能判断是否为同一个对象,但是hashcode不同的话肯定不是同一个对象,hashcode相同的不一定是同一个对象。

file

关注我不会让你失望哟~

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网