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[] 的值。

 

posted @ 2021-07-17 16:57  雪之下。  阅读(126)  评论(0)    收藏  举报