• String 引用传递还是值传递 String到底是什么


    今天群里讨论java的String类,顺着大家的讨论 做个简单的总结

    String就是引用类型,JAVA也是按值传递 都没毛病,有毛病的是 String这个包装类 的不同之处

    先说大众虚拟机中字符串的实现

    都说JAVA的一个类型对应着JVM中的一个CPP的类型,我们就来模拟一下,大概长这样。

    class JVMString{
     //存放字符串的内存地址
     char *s;
     //记录字符串的长度 
     int len;
    }
    
    

    现在JVM中String类有了,长度和存放字符串的地址都有了

    写一段JAVA代码来推敲

    
    class Test{
    
      void init(){
        String s = "方东信";
        set(s);
        
      }
      void set(String s){
       s ="方东信你好!";
      }
    
    }
    
    

    先说init方法

    s="方东信"

    • 这段代码JVM会new 一个JVMString对象(CPP) 我们假定这个CPP对象叫做A,A的地址是1011
    • JVM计算好这几个字符的长度(此处假设3个长度),存到A对象的属性len中,再分配3个内存块,接着把字符串存到这段内存中,再把这段内存的地址存到A对象s指针中
    • 此时JVM已经构造好了一个JVMString对象了,实际他就是一个JAVA的对象

    再谈set(s)方法

    按照传值的原则,JVM会生成一个Arg对象叫X。这个X对象中的ref指针指向A的地址1011 并把X传到set方法中

    s ="方东信你好!";

    当执行这段代码时,大家有什么想法? 因为底层对应的是CPP的对象,这个对象有个s指针,这个指针指向的内存块只有3个长度,但此出的代码中的字符串 可不是只有3个(想想JAVA中的定长数组,你要改变他的长度,你如何做?)
    此时有两种可能的做法:

    • JVM会根据当前的字符串长度重新分配一段内存,然后把字符串写进去,再把这个新的地址存到A对象的s指针中.此时的A还是原来的A,只是现在的A的s和之前的A的s指向的地址不同。

    这个方案,会造成在set中改变了字符串内容后,外部也改变。

    • jvm内部重新new一个JVMString对象 地址为1012. 分配好字符串。把1012这个地址存到X对象的ref指针中。这个时候,1012和1011已经完全不相干了

    这个方案,实际就是现在JVM的方案

    留给大家思考,为什么JVM不选择第一种方案?

    还是给出答案吧
    https://zhuanlan.zhihu.com/p/78946350
    https://www.jianshu.com/p/91406b649729

    特别说明

    文中的Arg对象实际是Handler对象,他对JVM中的栈中的对象进行了一次包装,目的是方便GC扫描。
    文中并没有严谨表达JVM内部执行流程和JVM底层对象结构,仅跑了个大概,勿杠。

  • 相关阅读:
    C语言 strcat
    C语言 strncpy
    C语言 strcpy
    C语言 main
    可显示Android设备选择列表,并进入指定Android设备Console的Shell脚本
    Android系统如何录制屏幕(录制成mp4格式)
    据说有99%的人都会做错的面试题
    一道淘汰85%面试者的百度开发者面试题
    用Android模拟器也可以开发和测试NFC应用
    一道腾讯面试题的思考:到底谁会赢?
  • 原文地址:https://www.cnblogs.com/cfas/p/15978732.html
Copyright © 2020-2023  润新知