赞
踩
@Test
public void test1() {
String s1 = "a" + "b" + "c"; //等同于"abc",//编译期优化
String s2 = "abc";
//最终.java编译成.class,再执行.class
// String s1 = "abc"; String s2 = "abc"
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
}
//执行结果
true
true
@Test public void test2() { String s1 = "javaEE"; String s2 = "hadoop"; String s3 = "javaEEhadoop"; String s4 = "javaEE" + "hadoop"; //编译期优化 //拼接符号的前后出现了变量,则相当于在堆空间中new String(),具体内容为拼接结果 String s5 = s1 + "hadoop"; String s6 = "javaEE" + s2; String s7 = s1 + s2; System.out.println(s3 == s4); //true System.out.println(s3 == s5); //false System.out.println(s3 == s6); //false System.out.println(s3 == s7); //false System.out.println(s5 == s6); //false System.out.println(s5 == s7); //false System.out.println(s6 == s7); //false //判断s6的值是否在常量池中,如果查到则直接返回常量池中的地址,如字符串常量池中不存在,则在常量池中加载一份,并返回此对象地址 String s8 = s6.intern(); System.out.println(s3 == s8); //true } @Test public void test3() { String s1 = "a"; String s2 = "b"; String s3 = "ab"; /** * s1 + s2执行细节 * StringBuilder sb = new StringBuilder(); * sb.append("a") * sb.append("b") * sb.toString()---------- * @Override---StringBuilder * public String toString() { * // Create a copy, don't share the array * return new String(value, 0, count); * } * * 在jdk5.0以后使用StringBuilder,5.0之前使用StringBuilder */ String s4 = s1 + s2; System.out.println(s3 == s4); //false } @Test public void test4() { /** * 1.字符串拼接不一定使用StringBuilder * 如果拼接符号左右两边都是字符串常量或常量引用,仍使用编译期优化,即非StringBuilder * 2.针对于final修饰类、方法、基本数据类型、引用数据类型的量的结构时,能使用上final时使用上 */ final String s1 = "a"; final String s2 = "b"; String s3 = "ab"; String s4 = s1 + s2; System.out.println(s3 == s4); //true } /** * 通过StringBuilder的append方式添加字符串效率要远高于使用String的字符串拼接方式 * 详情:①使用StringBuilder的append方式,自始至终只创建一个StringBuilder对象 * 使用String拼接的方式,每次循环会创建一个StringBuilder和一个String * ②使用String拼接方式,内存由于创建了较多的StringBuilder对象,占用内存大,GC耗时 * 改进空间:在实际开发中,如果能基本确定要前前后后添加的字符串长度不高于某个限定值highLevel情况下,建议使用构造器创建StringBuilder * StringBuilder sb = new StringBuilder(highLevel) */ @Test public void test5() { long start = System.currentTimeMillis(); //method1(100000); //花费时间:3641 method2(100000); //花费时间:0 long end = System.currentTimeMillis(); System.out.println("花费时间:" + (end - start)); } private void method1(int highLevel) { String src = ""; for (int i = 0; i < highLevel; i++) { src += "a"; //每次循环创建一个StringBuilder,String } } private void method2(int highLevel) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < highLevel; i++) { sb.append("a"); } }
/** * 如何保证变量s指向的是字符串常量池中的数据? * 方式①:String s = "lotus";//字面量定义的方式 * 方式②:调用intern()方法 * String s = new String("lotus").intern() * String s = new StringBuilder("lotus").toString().intern() */ public class StringIntern { public static void main(String[] args) { /** * new String("1"),会创建两个对象 * 对象1:new String("1") * 对象2:常量池中“1” */ String s = new String("1"); //s指向堆空间创建的字符串对象地址 s.intern(); String s2 = "1"; //s2指向常量池中对象地址 System.out.println(s == s2); //jdk6:false,jdk7/8:false /** * new String("1") + new String("1")会创建两个对象 * 对象1:new StringBuilder * 对象2:new String("1") * 对象3:常量池中“1” * 对象4:new String("2") * 对象5:常量池中“2” * 深入剖析:StringBuilder的toString() * 对象6:new String("12") * 强调,toString()调用,在常量也中没有生顾"12" */ String s3 = new String("1") + new String("2"); //s3变量地址为new String("12") /** * 在字符串常量池中生成"12" * jdk6:创建一个新的对象"12",也就有新的地址 * jdk7/8:此时常量池中并没有创建"12",而是创建一个指向堆空间的指针 */ s3.intern(); String s4 = "12"; //使用上一行代码执行时,在常量池中生成的"12"的地址 System.out.println(s3 == s4); jdk6:false,jdk7/8:true } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。