String变量内存分配

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wangjxy2013/article/details/48382723


    由JVM内存管理可知,在方法区中有一块独立的区域,被称之为运行时常量池,在虚拟机启动时,JVM会自动创建,有9种类型的常量池,8大基本类型与String类型。

   常量池是存放数据字面量的,比如“abc”,1,5.0,'c',true等等(注:String类的具体值,都是存在常量池中,堆中存的是常量池中的引用;8大基本类型的包装类中,除了Float,Double类意外,都有实现常量池,但是,数值类型的包装类要小于127的时候才会运用常量池,大于127就直接存储于栈中了。基本数据类型的数据是直接存放于栈中的;更多信息,参见博文《Integer与int小谈》);但是,String毕竟是一个类,而8大基本类型也有其对应的包装类;类就与堆离不开关系,下面就介绍下这些类的对象是如何徘徊再堆与常量池之间的。(注:由于8大基本类型与String差不多,这里只介绍String)。

1. String对象的创建。

    String对象有两种创建方式:

    a.通过字面量;String str = "wangjxy";

    b.通过new关键字创建;String str = new String("wangjxy");

    然而,这两种之间有非常大的差异。

    解释说明:第一:凡是出现"wangjxy"等形式的字符串赋值(即将该整体赋值给=号左边),都要与常量池进交互:先查询常量池 是否有该对象,若有,则直接将常量池中的该对象的引用返回给=号左边;若没有,则会先再常量池中把该对象添加  进去,然后返回该引用;如String str = "wangjxy";在编译的时候先会检查在常量池中有无"wangjxy"对象,并根据以上

 规则返回相应的引用给变量str; 

第二:String str = new String("wangjxy")的时候,首先,出现new关键字,肯定需要在堆中开辟相应的空间,同样,出

现了"wangjxy"字面量,也会在常量池中做相应的引用返回,因此,这时候,可能会在原先"wangjxy"对象上在堆中再创

 建一个,也有可能同时在堆与常量池中各创建一个,而变量str指向的是堆中该对象的地址,堆中引用的是常量池中的 

 字面量;因此:对于a方式,堆中开辟空间,变量指向的是常量池中的对象;对于b方式,变量str指向的是堆,具体该条语句产生几个对 象,由原先常量池中有无该对象决定。

     可解释代码:

   String str1 = "wangjxy";
   String str2 = new String("wangjxy");
// str1.equals(str2);->true
//  str1 == str2; ->false

2.String拼接。

    String拼接也有两种方式:

     a.String str = "a" + "b";

     b.String str1 = "a";

        String str2 = "b";

        String str3 =str1 +str2;

    解释说明:对于a方式,字面量拼接;由于字面量在编译器编译的时候,就能够解析到,所以在=号右面的所有字面量都会一起解析后,拼接完毕再以一个完整的字符串存到常量池中,并返回该整个字符串在常量池中的引用;

                      对于b方式,字符串变量的拼接,这时候,在编译的时候,编译器无法间接去取得变量对应的具体字面量,所以,它 会在运行时候首先在堆中动态的创建一个对象,然后根据对象中str1,str2两个变量的引用去取得拼接字面量,把拼接  好的字面量放入常量池并返回该引用给堆中对象;若已经有该字面量对象 ,则直接返回该引用;但str5指向的是堆中 的对象地址,而不是常量池中的字面量。

   可解释代码:

    

 String str1 = "a" + "b";
 String str2 = "ab";
 //str1 == str2; ->true;
  String str3 = "a";
  String str4 = "b";
  String str5 =str3 +str4;
//str5 == str2; -> false
3.带final字段的String拼接。    该种方式的拼接也有两种形式:     

a. String s1 = "ab";       

    final String s2 = "b";       

    String s3 = "a" + s2;  

 b. String s1 = "ab";

   String  s2 = "b";

   final String s3 = s2;

   String s4 = "a" + s3;

解释说明: 对于a方式,由于s2被final修饰,而且等号后面跟着直接可以读取的字面量,所以s2被直接解析为"b"而且把b写入了s2  变量中,所以 "a" + s2 就相当于 "a" + "b";对于b方式,虽然s3被final修饰,但是由于等号后面的是变量不是字面量,无

 法直接被编译器解析,所以同样只有等到程序执行的时候才能去读取,因此这里的s4同样会被动态分配堆空间;

        String s1 = "ab";
        final String s2 = "b";
        String s3 = "a" + s2;
        //s3 == s1;->true
        String s4 = "ab";
        String  s5 = "b";
        final String s6 = s5;
        String s7 = "a" + s6;
        //s7 == s4;->false
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值