美文网首页JAVA基础
String,StringBuffer,StringBuilde

String,StringBuffer,StringBuilde

作者: 梧桐花不开 | 来源:发表于2019-04-04 19:27 被阅读0次

    1.从源码角度分析三者是如何存储数据的

    String

    
    public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence {
        /** The value is used for character storage. */
        private final char value[];
    
    

    可以看到String和存储数据的char[],都有final关键字标志,是不可变对象。那String是如何做加法的呢,下面以这个代码为例:

    public static void main(String[] args) {
                String str = "";
                for (int i = 0; i < 100; i++) {
                    str += "demo ";
                }
        }
    

    反编译后:

      public static void main(java.lang.String[]);
        Code:
           0: ldc           #2                  // String
           2: astore_1
           3: iconst_0
           4: istore_2
           5: iload_2
           6: bipush        100
           8: if_icmpge     37
          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: ldc           #6                  // String demo
          24: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
          27: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
          30: astore_1
          31: iinc          2, 1
          34: goto          5
          37: return
    

    从第11行开始,发现字符串相加没加一次会新生成一个StringBuilder对象,这100次循环就要生成100次。如果循环次数再多,不及时回收会造成可观的内存浪费。

    StringBuffer

    StringBuffer继承AbstractStringBuilder,存储数据的是char[],非final

    abstract class AbstractStringBuilder implements Appendable, CharSequence {
        /**
         * The value is used for character storage.
         */
        char[] value;
    

    添加字符串时,append,进行以下操作:

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

    可以看到与String直接相加相比,不会生成过多的临时对象,较为省内存。同时,加了“synchronized”关键字保证了append数据的线程安全性。

    StringBuilder

    StringBuilder继承自AbstractStringBuilder,存储数据也是char[],非final

    abstract class AbstractStringBuilder implements Appendable, CharSequence {
        /**
         * The value is used for character storage.
         */
        char[] value;
    

    添加字符串时,append,进行以下操作:

    
    
     @Override
        public StringBuilder append(int i) {
            super.append(i);
            return this;
        }
    

    与StringBuffer类似,不会生成过多的临时对象,较为省内存。但是没有synchronized标识,是非线程安全。

    2. 你了解String吗

            String a = "hello";
            String b = "hello";
            String c=new String("hello");
            String d=new String("hello");
            System.out.println(a==b);
            System.out.println(a==c);
            System.out.println(c==d);
            System.out.println(a==c.intern());
    

    结果是:
    true
    false
    false
    true
    String是对象,新生成一个对象的时候,地址会不同,因此a!=c c!=d,那为什么会a==b?
    原来直接加“”的字符串时放在“常量池”中。变量a和b指向常量池中的同一位置,因此是相等的。而变量c的分配在堆(非常量池)上面的,所以是不相等的。
    常量池在JVM内存模型的什么位置?
    这个位置和JDK的版本有关。JDK6放在永久带,JDK常量池被分配在堆上。
    如何转换成常量string?
    String 提供的intern()即可。例如上个代码例子中“a==c.intern()”是相等的。

    参考
    http://java-performance.info/string-intern-in-java-6-7-8/

    相关文章

      网友评论

        本文标题:String,StringBuffer,StringBuilde

        本文链接:https://www.haomeiwen.com/subject/efvfiqtx.html