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
}
}
posted @   小猪快陶  阅读(60)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示