北京哪家制作网站好,苏州专业做网站公司哪家好,网站建设案例查询,服务中心网站建设意见字符串拼接
// 常量与常量的拼接结果放在常量池
// 常量池中不会存在相同的常量
String str1 a b;
System.out.println(str1 ab);// 拼接时有一个为变量#xff0c;则结果会放在堆中。
// 变量拼接的原理是 StringBuilder append 最后…字符串拼接
// 常量与常量的拼接结果放在常量池
// 常量池中不会存在相同的常量
String str1 a b;
System.out.println(str1 ab);// 拼接时有一个为变量则结果会放在堆中。
// 变量拼接的原理是 StringBuilder append 最后toString
// 查看字节码指令就可以看到详细过程
// 就是在堆空间中 new String
String a a;
String str2 a b;
System.out.println(str2 ab);// 拼接结果调用 intern 方法则主动将常量池中还没有的字符串对象放入字符串常量池并返回对应地址
// 如果常量池中有对应字符串对象则返回已有的字符串对象地址
String b b;
String str3 (a b).intern();
System.out.println(str3 ab);// final 修饰的变量在编译时就会进行赋值确定
String str4 a b;
System.out.println(str4 ab);// false
final String c c;
final String d d;
String str5 c d;
System.out.println(str5 cd);// true使用 StringBulider 进行拼接
int i 0;
String str ;
while (i 1000){str a;
}循环中每次 str “a” 都会创建一个 StringBuilder 然后toString。效率极低。 int i 0;
StringBuilder sb new StringBuilder();
while (i 1000){sb.append(a);
}
String str sb.toString();只 new 了一个StringBuilder且只 toString 一次。 进一步优化
int i 0;
StringBuilder sb new StringBuilder(1000);
while (i 1000){sb.append(a);
}
String str sb.toString();优化方式和ArrayList一样。如果我们能大概确定要生成的字符串长度我们可以初始化 StringBuilder 的底层 char[] 数组的长度避免超过长度时的扩容操作。 new String 会创建几个对象 String s new String(“ab”) 会创建两个对象。一个在堆空间一个在字符串常量池。此时 s 的地址为指向堆空间的字符串对象。 具体可以在 idea 中下载 jclasslib 插件查看字节码的方式来解释
引申
new String(a) new String(b) // 创建了几个对象
1. new String(a) 创建两个对象堆和常量池
2. new String(b) 创建两个对象堆和常量池
3. 两个非常量相加会创建一个 StringBuilder 对象使用其 append 方法最后 toString
4. toString 方法会 new 一个 String 对象但其不会在常量池生成对象abintern 方法的使用
public native String intern();intern 是一个 native 方法如果当前常量池没有当前字符串对应相等equals 为 true的字符串则将对象放入字符串常量池并返回对应地址。如果常量池中有对应字符串对象则返回已有的字符串对象地址 示例
String a new String(a);
a.intern();
System.out.println(a a); //jdk6 false jdk1.7 falseString b new String(b) new String(b);
b.intern();
System.out.println(b bb);//jdk6 false jdk1.7 true对象 a 指向的时堆中的字符串对象地址“a” 放在常量池的所以为 false new String(“b”) new String(“b”) 不会在常量池创建对象 “ab”其主要问题是jdk1.7 环境中在调用 intern 方法的时候不是在常量池中创建一个新的对象 “ab”而是将当前堆中 new 的 “ab” 的引用赋值给了常量池的引用导致堆和常量池中的引用都指向了同一个地址。基于此特性下面的示例结果就能够解释了。 String c new String(c) new String(c);
String cc cc;
c.intern(); // 当前 cc 在常量池已经存在且和堆中的对象引用不同
System.out.println(c cc);// jdk1.7 falseString d new String(d) new String(d);
d.intern();// 此时 dd 在常量池还不存在基于上面的解释此时堆和常量池中的dd对象的引用是一致的
String dd dd;
System.out.println(d dd);// jdk1.7 trueintern 使用技巧 大量的 String 对象使用的时候比如String 数组或大的集合中存放 String 对象可以对String对象先调用 intern 方法返回常量池引用后存放。这样的好处是最后这些大量的引用都引用的常量池的对象堆中的对象可以正常 GC 释放。此方式特别在有大量重复字符串对象的时候能节省大量的空间。