String中的intern()小结
Java中字符串的创建方式有两种:
(1)通过 “ ” 直接创建字符串,即静态字面量创建字符串,该字符串会放入字符串常量池中
(2)通过 new 关键字创建字符串,当字符串常量池中不包含相同的字符串时,此时会创建两个对象,一个在堆中,一个在字符串常量池中;当字符串常量池中包含相同的字符串时。此时只会创建一个对象,即在堆中。(注意含有变量拼接创建的字符串不会放入字符串常量池中)
String 的 “+” 拼接字符串:
- 当都是静态字符串相加的结果会添加到常量池,如果常量池中有这个结果则直接返回其引用;如果没有,则创建该字符串再返回引用。
- 当含有变量的时候,拼接后的字符串不会进入字符串常量池中,其真正实现的原理是中间通过建立临时的StringBulider对象,然后调用append方法拼接字符串,最后再通过StringBulider的toString方法转化出一个新的String对象。
String中的intern()方法:
When the intern method is invoked, if the pool already contains a string equal to this {@code String} object as determined by the {@link #equals(Object)} method, then the string from the pool is returned. Otherwise, this {@code String} object is added to the pool and a reference to this {@code String} object is returned.
翻译后:
当调用intern方法时,如果池已经包含与equals(Object)方法确定的相当于此String对象的字符串,则返回来自池的字符串。 否则,此String对象将添加到池中,并返回对此String对象的引用。
public class StringIntern { public static void main(String[] args) { /** * 首先,在字符串常量池中创建 “ja” 和 “va” 两个对象, * 由于java是关键字,所以字符串常量池中是默认存在的 * 然后在堆中开辟“ja” 和 “va” 两个对象空间, * 所以s1.intern()返回的是默认存在的java对象的地址,并不是程序员创建的 * 而s1的地址在堆中,故一个地址常量池一个在堆中 输出false **/ String s1 = new String("ja") + new String("va"); System.out.print("s1.intern()==s1: "); System.out.println(s1.intern() == s1);//false System.out.print("s1==\"java\": "); System.out.println(s1 == "java");//false System.out.println("----------------------------"); /** * 首先,在字符串常量池中创建 “va” 和 “ja” 两个对象, * 并在堆中开辟两个对象空间,由于没有对象没有被引用会被直接销毁,此步骤可以忽略 * 然后底层会创建一个StringBuilder来拼接 “va” 和 “ja” 两个对象,在堆中开辟 “vaja” 对象的空间, * 当前,字符串常量池中并没有 “vaja” * 当调用s2.intern()方法时,将堆中 “vaja” 对象的引用 加入字符串常量池中 **/ String s2 = new String("va") + new String("ja"); System.out.print("s2.intern() == s2: "); System.out.println(s2.intern() == s2);//true System.out.print("s2 == \"vaja\": "); System.out.println(s2 == "vaja");//true System.out.println("----------------------------"); /** *首先,在字符串常量池中创建 “1” 对象 * 在堆中开辟 “1” 的对象空间 * 由于 字符串常量池中 “1” 对象已存在,故当调用intern()方法时,返回的是字符串常量池中的对象 * 一个对象在堆中,一个在字符串常量池中,故输出false **/ String s3 = new String("1"); System.out.print("s3.intern()==s3: "); System.out.println(s3.intern() == s3);//false System.out.print("s3 == \"1\": "); System.out.println(s3 == "1");//false System.out.println("----------------------------"); /** *首先,在字符串常量池中创建 “2” 对象 * 在堆中开辟 “2” 对象空间和 “22” 对象空间 * 当调用intern方法时,会将堆中 “22” 的引用加入字符串常量池,故输出true **/ String s4 = new String("2") + new String("2"); System.out.print("s4.intern()==s4: "); System.out.println(s4.intern() == s4);//true System.out.print("s4==\"22\": "); System.out.println(s4 == "22");//true System.out.println("----------------------------"); /** *当没有出现变量进行拼接时拼接完的字符串会放置到字符串常量池, * 一旦对象中出现变量,则会通过StringBuilder的append拼接两个字符串, * 然后通过toString方法再new出新的对象。 * StringBuilder或者StringBuffer拼接得到的字符串只会在堆中创建对象,不会在字符串常量池中创建对象 * 当调用intern方法时,会将拼接字符串对象的引用存放到字符串常量池 **/ String s5 = "小猪"; String s6 = "快逃"; String s7 = s5 + s6; s7.intern(); String s8 = "小猪" + "快逃"; System.out.print("s7 == s8: "); System.out.println(s7 == s8);//true System.out.println("----------------------------"); StringBuilder stringBuilder = new StringBuilder("s").append("b"); String s9 = new String(stringBuilder.toString()); System.out.print("s9.intern() == s9: "); System.out.println(s9.intern() == s9);//true StringBuffer stringBuffer = new StringBuffer("b").append("s"); String s10 = new String(stringBuffer.toString()); System.out.print("s10.intern() == s10: "); System.out.println(s10.intern() == s10);//true } }
Do more and talk less!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)