String 简单分析

来源:互联网 发布:vscode debug webpack 编辑:程序博客网 时间:2024/06/05 04:36

        • String 基本常识
        • String 内存分配
          • 直接赋值
          • 通过new
        • String 的比较主要是 equals
        • String StringBuffer StringBuilder

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));

输出

truefalsefalsetruetruetrue

关于 == 和 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

我只能说显而易见了

原创粉丝点击