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 }