1 package day2_7; 2 3 import org.junit.Test; 4 5 /** 6 * String:字符串,一般使用一对 "" 引起来表示 7 * 8 * public final class String 9 * implements java.io.Serializable, Comparable<String>, CharSequence { 10 * private final char value[]; 11 .... 12 } 13 * 14 * 1.String类声明为final,说明不可被继承 15 * 2.String继承了Serializable,说明是可序列化的 16 * String继承了Comparable,说明是可以比较大小的 17 * 3.String内部定义了 private final char value[];用于存储字符串数据 18 * 4.String代表不可变的字符序列,简称:不可变性 19 * 体现:1.当对字符串重新赋值时,需要重新指定内存区域赋值,不能使用原有的value进行赋值 20 * 2.当对现有字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值 21 * 3.当调用replace()修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值 22 * 5.通过字面量的方式(区别于new的)给一个字符串赋值,此时的字符串值声明在字符串常量池中 23 * 6.字符串常量池是不会存储相同内容的字符串的 24 * 25 * 26 * @Author Tianhao 27 * @create 2021-02-07-17:31 28 */ 29 public class StringTest { 30 31 @Test 32 public void test1() { 33 String s1 = "abc"; //字面量的定义方式 34 String s2 = "abc"; 35 System.out.println(s1 == s2); //比较地址值 true 36 s1 = "hello"; 37 System.out.println(s1 == s2); //比较地址值 false 38 System.out.println(s1); //hello 39 System.out.println(s2); //abc 40 41 System.out.println("*****************"); 42 String s3 = "abc"; 43 s3 += "def"; 44 System.out.println(s3); //abcdef 45 System.out.println(s2); //abc 46 47 System.out.println("****************"); 48 String s4 = "abc"; 49 String s5 = s4.replace("ab", "de"); 50 System.out.println(s5); //dec 51 System.out.println(s4); //abc 52 53 } 54 55 /** 56 *String的实例化方式 57 * 方式一:通过字面量定义的方式 58 * 方式二:通过new + 构造器的方式 59 * 60 * 61 * 面试题: String s = new String("abc"); 通过这种方式创建对象,在内存中创建了几个对象? 62 * 两个:一个是new的String对象结构, 63 * 另一个是其类中的char[] value成员变量对应的方法区字符串常量池中的数据"abc" 64 */ 65 66 @Test 67 public void test2() { 68 //通过字面量定义的方式 69 // 此时的s1、s2指向的数据JaveEE都声明在方法区中的字符串常量池中 70 String s1 = "JavaEE"; 71 String s2 = "JavaEE"; 72 73 //通过new + 构造器的方式 74 //// 此时的s3、s4保存的地址值,是数据在堆空间开辟空间以后对应的地址值 75 String s3 = new String("JavaEE"); 76 String s4 = new String("JavaEE"); 77 78 System.out.println(s1==s2);//true 79 System.out.println(s1==s3);//false 80 System.out.println(s1.equals(s3)); //true 81 System.out.println(s1==s4);//false 82 System.out.println(s1.equals(s4)); //true 83 System.out.println(s3==s4);//false 84 System.out.println(s3.equals(s4)); //true 85 86 87 System.out.println("*********************"); 88 89 Person p1 = new Person("Tom", 23); 90 Person p2 = new Person("Tom", 23); 91 Person p3 = new Person(new String("Tom"), 23); 92 //每new一次,堆就重新开辟一个空间,把地址值赋给引用对象,地址值都是不一样的 93 System.out.println(p1 == p2); //false 94 //因为Person类没有重写Object的equals(),所以默认还是 == ,比较对象地址值 95 System.out.println(p1.equals(p2));//false 96 //两个对象都是通过字面量赋值,指向方法区字符串常量池中同一个数据Tom,所以地址值相同 97 System.out.println(p1.name == p2.name);//true 98 //因为String类重写了Object的equals(),比较的是字符串内容 99 System.out.println(p1.name.equals(p2.name)); //true 100 //每new一次,堆就重新开辟一个空间,把地址值赋给引用对象,地址值都是不一样的 101 System.out.println(p1 == p3); //false 102 //p1的name是通过字面量赋值,p3的name是通过new+构造器方式赋值 103 //前者是指向方法区常量池中的数据Tom,后者是指向堆空间的String对象的char[]类型的成员变量value 104 //显然两者的地址值是不同的 105 System.out.println(p1.name == p3.name);//false 106 //因为String类重写了Object的equals(),比较的是字符串内容 107 System.out.println(p1.name.equals(p3.name)); //true 108 109 } 110 111 112 /** 113 * 114 * 结论: 115 * 1.常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量 116 * 2.只要其中一个是变量,结果就在堆中 117 * 3.如果拼接的结果调用intern(),返回值就在常量池中 118 * 119 */ 120 121 @Test 122 public void test3() { 123 String s1 = "Hello"; 124 String s2 = "World"; 125 String s3 = "HelloWorld"; 126 String s4 = "Hello" + "World"; 127 String s5 = "Hello" + s2; 128 String s6 = s1 + "World"; 129 String s7 = s1 + s2; 130 String intern = s5.intern(); 131 132 System.out.println(s3 == s4); 133 134 System.out.println("*** 带变量的拼接 ***"); 135 System.out.println(s3 == s5); 136 System.out.println(s3 == s6); 137 System.out.println(s3 == s7); 138 System.out.println(s4 == s5); 139 System.out.println(s4 == s6); 140 System.out.println(s4 == s7); 141 System.out.println(s5 == s6); 142 System.out.println(s5 == s7); 143 System.out.println(s6 == s7); 144 145 System.out.println("**** intern()方法 *****"); 146 System.out.println(s3 == intern); 147 System.out.println(s4 == intern); 148 System.out.println(s5 == intern); 149 System.out.println(s6 == intern); 150 } 151 152 }