String常量和变量、String、StringBuffer与StringBuilder之间区别

一、Java中字符串常量和字符串变量的区别

https://blog.csdn.net/u010617952/article/details/51781319
~~~~字符串常量池实现的前提条件:Java中String对象是不可变的,这样可以安全保证多个变量共享同一个对象。如果Java中的String对象可变的话,一个引用操作改变了对象的值,那么其他的变量也会受到影响,显然这样是不合理的。

    String s1 = "s";    //不可变对象,字符串常量,先在字符串常量池里搜索,没有,则new,再加入,成拘留字符串;有就直接引用。
    String s2 = "s";
        
    System.out.println("s1 == s2:" + (s1 == s2));    //true,注意添加括号,字符串拼接优先于判定
        
    String s3 = new String("s");    //字符串变量,不管常量池中有没有,都会创建新对象
    System.out.println("s1 == s3:" + (s1 == s3));    //false
        
    String s4 = s3.intern();    //intern()将其加入字符串常量池
    System.out.println("s4 == s3:" + (s4 == s3));    //false
    System.out.println("s1 == s4:" + (s1 == s4));    //true

二、Java中字符串拼接的一些细节分析

https://www.jb51.net/article/59934.htm

  • 内部编译器优化,连续用+拼接,只创建一个对象。
String s = "1" + "2" + "3";
  • 如果是for循环用+拼接,会隐式创建StringBuilder,有多少个循环创建多少个。因此,要避免在for循环内隐式或显式创建StringBuilder,提升性能。
  • 在for循环外部显式创建StringBuilder,使用append方法,再toString即可。
    int[] arr = new int[] {1,2,3};
    StringBuilder sb = new StringBuilder();
    for(int i : arr) {sb.append(i);}
    System.out.println(sb.toString());

三、String、StringBuffer与StringBuilder之间区别

https://blog.csdn.net/itchuxuezhe_yang/article/details/89966303

LY$`$[_L@5(GW7{X]DK%`)W.png

1. String类型脱光了其实也很普通。真正让她神秘的原因就在于CONSTANT_String_info常量表拘留字符串对象的存在。

  • 【纷争一】关于字符串相等关系的争论
    ~~~~上面第一部分已写明。

  • 【纷争二】字符串“+”操作的内幕

//代码1  
String sa = "ab";                                          
String sb = "cd";                                       
String sab=sa+sb;                                      
String s="abcd";  
System.out.println(sab==s); //false  
//代码2  
String sc="ab"+"cd";  
String sd="abcd";  
System.out.println(sc==sd); //true

~~~~代码1中局部变量sa,sb存储的是堆中两个拘留字符串对象的地址。而当执行sa+sb时,JVM首先会在堆中创建一个StringBuilder类,同时用sa指向的拘留字符串对象完成初始化,然后调用append方法完成对sb所指向的拘留字符串的合并操作,接着调用StringBuilder的toString()方法在堆中创建一个String对象,最后将刚生成的String对象的堆地址存放在局部变量sab中。而局部变量s存储的是常量池中"abcd"所对应的拘留字符串对象的地址。 sab与s地址当然不一样了。这里要注意了,代码1的堆中实际上有五个字符串对象:三个拘留字符串对象、一个String对象和一个StringBuilder对象。
~~~~代码2中"ab"+"cd"会直接在编译期就合并成常量"abcd", 因此相同字面值常量"abcd"所对应的是同一个拘留字符串对象,自然地址也就相同。
~~~~总结:字符串引用相“+”,会创建StringBuilder,append合并,再new一个新对象作为结果。拘留字符串相“+”,在编译器就合并,成为拘留字符串。

2. String三姐妹(String,StringBuffer,StringBuilder)

  • StringBuffer与String的可变性问题
//String   
public final class String  
{  
        private final char value[];  //final,不可变
  
         public String(String original) {  
              // 把原字符串original切分成字符数组并赋给value[];  
         }  
}  
  
//StringBuffer   
public final class StringBuffer extends AbstractStringBuilder  
{  
         char value[]; //继承了父类AbstractStringBuilder中的value[]  ,可变
         public StringBuffer(String str) {  
                 super(str.length() + 16); //继承父类的构造器,并创建一个大小为str.length()+16的value[]数组  
                 append(str); //将str切分成字符序列并加入到value[]中  
        }  
}

~~~~总结:本质上是指对象中的value[]字符数组可不可变,而不是对象引用可不可变。

  • String和StringBuffer的效率问题

(1) String常量与String变量的"+"操作比较

    String str = "";
    str="Heart" + "Raid";

    String s1 = "Heart";
    String s2 = "Raid";
    String str = "";
    str = s1 + s1;

~~~~结论:String常量的“+连接” 稍优于 String变量的“+连接”。
~~~~原因:测试①的"Heart"+"Raid"在编译阶段就已经连接起来,形成了一个字符串常量"HeartRaid",并指向堆中的拘留字符串对象。运行时只需要将"HeartRaid"指向的拘留字符串对象地址取出1W次,存放在局部变量str中。这确实不需要什么时间。

(2) String对象的"累+"连接操作与StringBuffer对象的append()累和连接操作比较

    String s1="Heart";
    String s="";
    s=s+s1;

    String s1="Heart";
    StringBuffer sb=new StringBuffer();
    sb.append(s1);

~~~~结论:大量字符串累加时,StringBuffer的append()效率远好于String对象的"累+"连接
~~~~原因:测试① 中的s=s+s1,JVM会利用首先创建一个StringBuilder,并利用append方法完成s和s1所指向的字符串对象值的合并操作,接着调用StringBuilder的 toString()方法在堆中创建一个新的String对象,其值为刚才字符串的合并结果(就是字符串变量相+)。而局部变量s指向了新创建的String对象。

总结:
~~~~(1) 在编译阶段就能够确定的字符串常量,完全没有必要创建String或StringBuffer对象。直接使用字符串常量的"+"连接操作效率最高。
~~~~(2) StringBuffer对象的append效率要高于String对象的"+"连接操作。
~~~~(3) 不停的创建对象是程序低效的一个重要原因。那么相同的字符串值能否在堆中只创建一个String对象。显然拘留字符串能够做到这一点,除了程序中的字符串常量会被JVM自动创建拘留字符串之外,调用String的intern()方法也能做到这一点。当调用intern()时,如果常量池中已经有了当前String的值,那么返回这个常量指向拘留对象的地址。如果没有,则将String值加入常量池中,并创建一个新的拘留字符串对象。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容