String 简单分析

String 基本常识
  1. 通过直观看代码得到的 String 是 final 的不可继承
  2. String 对象是不可变的。查看源码或者JDK文档可以看出来,String里面每一个会修改String值的方法,都会创建一个新的对象
  3. 基于 特征2 所以涉及到String的效率问题
String 内存分配
  1. 常量池

这里面有个隐藏的问题,就是关于常量池的位置。
在JDK1.6以前(包括JDK1.6)常量池是在*方法区
在JDK1.7的时候常量池移到了
具体的变化请自行参考JVM相关资料

String a = "a";
String b = "a";
String c = new String("b");
String d = new String("a");
String e = new String("b");
直接赋值

首先在常量池判断是否存在a,如果不存在则在常量池开辟一块空间存放a,如果存在则不用开辟空间。
然后在栈中开辟一块空间存放常量池中a的内存地址,并且命名为a

通过new

首先在常量池判断是否存在b,如果不存在则在常量池开辟一块空间存放b,如果存在则不用开辟空间。
然后在内存堆中开辟一块空间存放new出来的对象
然后在栈中开辟一块空间存放内存堆中a的内存地址,并且命名为c

关于堆里面的String对象和常量池里面的String常量之间的的联系,一脸懵逼,望高手解答

String 的比较主要是 == equals

通过这俩个判断可以验证上面的问题

        System.out.println(a == b);
        System.out.println(a == d);
        System.out.println(c == e);

        System.out.println(a.equals(b));
        System.out.println(a.equals(d));
        System.out.println(c.equals(e));

输出

true
false
false
true
true
true

关于 == 和 equals 请参考Java equals == 简单分析
a与b都是存放常量池的内存地址,所以a与b == 返回 true
a与b内容一致,所以a与b equals 返回true
d存放的是堆的内存地址,所以a与d == 返回 false
a与d内容一致,所以a与b equals 返回true
c与e存放的是不同的堆的内存地址,所以c与e == 返回 false
c与e内容一致,所以a与b equals 返回true

String StringBuffer StringBuilder

基于 String 的不可变行带来的效率问题引出来
StringBuffer StringBuilder
后俩者的主要是区别,可以直接通过代码得到

StringBuffer

    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

StringBuilder

    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

分析
String通过“+”进行操作的时候,由于String是不可变的,所以每次操作都会产生一个新的String对象,依次类推,最后会产生一大堆需要垃圾回收的中间对象。
这个要说明一个问题,就是本身编译器是使用StringBuilder对代码进行了优化了。但是还是不是最优的,可以通过 javap 进行查看

    public String stringAppend() {
        String result = "";
        for (int i = 0; i < 10; i++) {
            result += String.valueOf(i);
        }
        return result;
    }

    public String sbAppend() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            sb.append(i);
        }
        return sb.toString();
    }
  public java.lang.String stringAppend();
    Code:
       0: ldc           #2                  // String 
       2: astore_1      
       3: iconst_0      
       4: istore_2      
       5: iload_2       
       6: bipush        10
       8: if_icmpge     39 // 开始一个循环体
      11: new           #3                  // class java/lang/StringBuilder
      14: dup           
      15: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V // 这个地方很关键 在循环体里面去构造对象
      18: aload_1       
      19: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      22: iload_2       
      23: invokestatic  #6                  // Method java/lang/String.valueOf:(I)Ljava/lang/String;
      26: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      29: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      32: astore_1      
      33: iinc          2, 1
      36: goto          5 // 结束循环体
      39: aload_1       
      40: areturn 
  public java.lang.String sbAppend();
    Code:
       0: new           #3                  // class java/lang/StringBuilder
       3: dup           
       4: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V // 只构造一次对象
       7: astore_1      
       8: iconst_0      
       9: istore_2      
      10: iload_2       
      11: bipush        10
      13: if_icmpge     28
      16: aload_1       
      17: iload_2       
      18: invokevirtual #8                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      21: pop           
      22: iinc          2, 1
      25: goto          10
      28: aload_1       
      29: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      32: areturn

我只能说显而易见了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值