1 packageday2_7;2
3 importorg.junit.Test;4
5 /**
6 * String:字符串,一般使用一对 "" 引起来表示7 *8 * public final class String9 * implements java.io.Serializable, Comparable, 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 Tianhao27 * @create 2021-02-07-17:3128 */
29 public classStringTest {30
31 @Test32 public voidtest1() {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 @Test67 public voidtest2() {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); //false94 //因为Person类没有重写Object的equals(),所以默认还是 == ,比较对象地址值
95 System.out.println(p1.equals(p2));//false96 //两个对象都是通过字面量赋值,指向方法区字符串常量池中同一个数据Tom,所以地址值相同
97 System.out.println(p1.name == p2.name);//true98 //因为String类重写了Object的equals(),比较的是字符串内容
99 System.out.println(p1.name.equals(p2.name)); //true100 //每new一次,堆就重新开辟一个空间,把地址值赋给引用对象,地址值都是不一样的
101 System.out.println(p1 == p3); //false102 //p1的name是通过字面量赋值,p3的name是通过new+构造器方式赋值103 //前者是指向方法区常量池中的数据Tom,后者是指向堆空间的String对象的char[]类型的成员变量value104 //显然两者的地址值是不同的
105 System.out.println(p1.name == p3.name);//false106 //因为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 @Test122 public voidtest3() {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 }