Java常用类--String(一)Stirng的存储
String类的特性
- 1.String声明为final的,不可被继承
- 2.String实现了Serializable接口:表示字符串是支持序列化的。
- 实现了Comparable接口:表示String可以比较大小
- 3.String内部定义了final char[] value用于存储字符串数据
- 4.String:代表不可变的字符序列。简称:不可变性。
体现:
-
- 1.当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值。
- 2. 当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
- 3. 当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。

即方法区中不能含有两个值相同的地址空间,原S1 = S2时两个变量指向的地址是相同的,当s1的值改变时,方法区中重新划出一块地址空间并重新赋值,s1指向新的地址空间。
1 @Test 2 public void test1(){ 3 String s1 = "abc";//字面量的定义方式 4 String s2 = "abc"; 5 s1 = "hello"; 6 7 System.out.println(s1 == s2);//比较s1和s2的地址值 8 9 System.out.println(s1);//hello 10 System.out.println(s2);//abc 11 12 System.out.println("*****************"); 13 14 String s3 = "abc"; 15 s3 += "def"; 16 System.out.println(s3);//abcdef 17 System.out.println(s2); 18 19 System.out.println("*****************"); 20 21 String s4 = "abc"; 22 String s5 = s4.replace('a', 'm'); 23 System.out.println(s4);//abc 24 System.out.println(s5);//mbc 25 26 }
- 5.通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中。
- 6.字符串常量池中是不会存储相同内容的字符串的。
String对象的创建
方式一:通过字面量定义的方式
方式二:通过new + 构造器的方式
1 @Test 2 public void test2(){ 3 //通过字面量定义的方式:此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中。 4 String s1 = "javaEE"; 5 String s2 = "javaEE"; 6 //通过new + 构造器的方式:此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值。 7 String s3 = new String("javaEE"); 8 String s4 = new String("javaEE"); 9 10 System.out.println(s1 == s2);//true 11 System.out.println(s1 == s3);//false 12 System.out.println(s1 == s4);//false 13 System.out.println(s3 == s4);//false 14 15 System.out.println("***********************"); 16 Person p1 = new Person("Tom",12); 17 Person p2 = new Person("Tom",12); 18 19 System.out.println(p1.name.equals(p2.name));//true 20 System.out.println(p1.name == p2.name);//true 21 22 p1.name = "Jerry"; 23 System.out.println(p2.name);//Tom 24 }
结论:
1.常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。
2.只要其中有一个是变量,结果就在堆中。
3.如果拼接的结果调用intern()方法,返回值就在常量池中
1 @Test 2 public void test4(){ 3 String s1 = "javaEEhadoop"; 4 String s2 = "javaEE"; 5 String s3 = s2 + "hadoop"; 6 System.out.println(s1 == s3);//false 7 8 final String s4 = "javaEE";//s4:常量 9 String s5 = s4 + "hadoop"; 10 System.out.println(s1 == s5);//true 11 12 } 13 14 @Test 15 public void test3(){ 16 String s1 = "javaEE"; 17 String s2 = "hadoop"; 18 19 String s3 = "javaEEhadoop"; 20 String s4 = "javaEE" + "hadoop"; 21 String s5 = s1 + "hadoop"; 22 String s6 = "javaEE" + s2; 23 String s7 = s1 + s2; 24 25 System.out.println(s3 == s4);//true 26 System.out.println(s3 == s5);//false 27 System.out.println(s3 == s6);//false 28 System.out.println(s3 == s7);//false 29 System.out.println(s5 == s6);//false 30 System.out.println(s5 == s7);//false 31 System.out.println(s6 == s7);//false 32 33 String s8 = s6.intern();//返回值得到的s8使用的常量值中已经存在的“javaEEhadoop” 34 System.out.println(s3 == s8);//true 35 36 37 }
问:String s = new String("abc");方式创建对象,在内存中创建了几个对象?
答:两个;一个是堆空间中new结构,另一个是char[]对应的常量池中的数据:"abc"
一道面试题:
1 public class StringTest { 2 3 String str = new String("good"); 4 char[] ch = { 't', 'e', 's', 't' }; 5 6 public void change(String str, char ch[]) { 7 str = "test ok"; 8 ch[0] = 'b'; 9 } 10 public static void main(String[] args) { 11 StringTest ex = new StringTest(); 12 ex.change(ex.str, ex.ch); 13 System.out.println(ex.str);//good 14 System.out.println(ex.ch);//best 15 } 16 }
因为基本数据类型传入的是数据,引用数据类型传入的是地址值。由于String是不可变型,调用change方法时,str和传入的str指向同一个地址,但是方法体中的str改变了,产生了一个新的地址,但是原str指向的地址中的值并没有变。所以str依然是good,方法体中的str为 test ok,此时的str只是一个局部变量,如果在方法体中用sout输出str则会输出test ok。
又因为char[]虽然也是引用数据类型,但并没有不可变型,所以可以在方法体中直接对数组进行操作,所以可以改变char[] 的值。



浙公网安备 33010602011771号