Java String的intern以及StringBuilder


package string_;

public class String02 {
    public static void main(String[] args) {
        String str00 = new StringBuilder().append("purple").toString();
        String str01 = new StringBuilder("zxcvasdf").toString();
        String str02 = str00.intern();
        String str03 = str01.intern();
        String str04 = new StringBuilder().append("pi").append("nk").toString();
        String str05 = str04.intern();
        System.out.println(str00 == str02);//false
        System.out.println(str01 == str03);//false
        System.out.println(str04 == str05);//true
    }
}

输出结果

img

上述代码中为何一个append和两个append结果不一样呢?

个人理解:
一个append的情况,因为你代码里直接声明了这个字符串,所以都会直接在常量池中创建对应的字符串,而后面stringbuild tostring则是在堆上创建了对象,所以你的str00是堆上的对象,而str00, intern之后返回的是常量池中的字符串对象,所以二者不是同一个对象。

两个append的情况,没有直接在池中生成完整的字符串对象,str04是堆上的对象,调用intern的时候,因为池中没有,返回的是str04。

调用intern方法时,如果池中已包含一个字符串,该字符串等于由equals(object)方法确定的该字符串对象,则返回池中的字符串。否则,将此字符串对象添加到池中,并返回对该字符串对象的引用。

  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/227640
  • 这篇博客你也可以参考下:Java StringBuilder常见操作总结
  • 除此之外, 这篇博客: 324学习日记(String 和StringBuffer定义的字符串的区别、StringBuffer对象定义的字符串实现字符串反转操作、StringBuilder和StringBuffer的区别、中的 ").append("") 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • String 和 StringBuffer的区别:

    String:

    public class demo324{
        public static void main(String[] args) {
            String message="hxw";
            change(message);
            System.out.println(message);
        }
        public static void change(String s){
          s+="handsome";
        }
    }
    

    执行结果:

    hxw

    StringBuffer:

    public class demo324{
        public static void main(String[] args) {
            StringBuffer buffer=new StringBuffer();
            buffer.append("hxw").append("aodi").append("rs7");
            change(buffer);
            System.out.println(buffer);
        }
        public static void change(StringBuffer s){
            s.append("he is").append("car");
        }
    }

    执行结果:

    hxwaodirs7he iscar
     

    对比之下可以看出,String 声明后无法改变值,而通过StringBuffer的对象存的字符串可以通过append()方法随意在后面加字符串。

    StringBuffer对象定义的字符串实现字符串反转操作:(特色操作)

    public class demo324{
        public static void main(String[] args) {
            StringBuffer buffer=new StringBuffer(32);//这个capacity是形容可以容纳多少个字符串,默认值是16,调用append方法时会自动增加。这就是可以改变字符串长度的原因。
            buffer.append("hxw ").append("'s ").append("car is ").append("aodi RS7");
            System.out.println(buffer.reverse());//因为通过StringBuffer源代码可以发现,保存形式为Byte[],所以调用reverse方法进行反转操作。
        }
    }

    执行结果:

    7SR idoa si rac s' wxh

    StringBuffer中的insert方法:insert(offse,数据类型); //offset指的是索引位置。

    public class demo324{
        public static void main(String[] args) {
            StringBuffer buffer=new StringBuffer(32);//这个capacity是形容可以容纳多少个字符串,默认值是16,调用append方法时会自动增加。这就是可以改变字符串长度的原因。
            buffer.append("hxw ").insert(0,"'s car is aodiRS7");
            System.out.println(buffer);//因为通过StringBuffer源代码可以发现,保存形式为Byte[],所以调用reverse方法进行反转操作。
        }
    }
    执行结果:
    's car is aodiRS7hxw 
    

    类似方法还有replace(索引开始位置,索引结束位置);替换方法,

    还有delete(索引开始位置,索引结束位置);删除方法。

    String中有常量池、运行常量池、静态常量池。其实更实用。

    StringBuilder和StringBuffer的区别 

     

  • 以下回答由chatgpt基于相关博客总结生成:

    Java中String的intern方法是将字符串放入常量池中,如果常量池中已经有该字符串,则返回常量池中的字符串,否则会将该字符串加入到常量池中,并返回该字符串的引用。如果两个字符串内容相同,它们的intern方法返回的引用会相同。

    使用StringBuilder来构建字符串可以通过多个append方法来实现,但是需要注意的是,每次append都会创建一个新的String对象并将其添加到StringBuilder中,因此如果多次调用append,会生成多个不必要的String对象,浪费空间和时间。为了避免这种情况,可以使用StringBuilder的一个由参数的构造函数,该构造函数可以指定StringBuilder的初始容量,这样就可以避免多次扩容,提高效率。

    同时,建议在需要大量字符串操作的时候,使用StringBuilder来构建字符串,因为传统的String操作会创建很多无用的String对象,占用大量内存和CPU资源,而StringBuilder可以避免这种情况。