Java中String类知识点总结

 博客原文 ----> https://www.yanzhaochang.top/read/11

    String 字符串总结

        String被声明为final,因此它不可被继承,是常量,不可变的。

      a) 不可变的好处

           1. 可以缓存hash值   

              因为String和hash值经常被使用,例如Stirng用作HashMap的key。不可变的特性还可以保证hash值不可变,因此只需要进行一次计算,这也是一种性能的优化手段。

           2. String Pool的需要

               字符串常量池(String pool String 保留池 String 保留池)是Java堆中一个特殊的储存区域。

               创建对象时,假如此字符串已经存在于常量池中,就会从String Pool中取得引用,不会再创建。只有String是不可变的,才可能使用String Pool。 

               例:

                    Java中String类知识点总结_第1张图片

         3 安全性

               String 被许多的Java类库用来当作参数,例如:网络的连接地址、文件路径Path、反射中使用的String类型的参数,如果String不是固定不变的,将会引入各种安全隐患。

      b) 字符串缓冲池

              JVM为了提升性能和减少内存的开销,避免字符串的重复创建,在内存中会单独开辟出一块单独的区域,用来储存字符串对象,这块内存区域被称为字符串缓冲池。

     String s1 = "test";
     String s2 = "test";
     String s3 = new String("test");
     String s4 = new String("test");
     String s5 = new String("test2");
     System.out.print(s1==s2);
     System.out.print(s1==s3);
     System.out.print(s2==s3);
     System.out.print(s3==s4);

          结果:

            true false false true

         解析:

            1 对于s1,在创建字符串的时候,JVM虚拟机会先去缓冲池中查找是否存在"test"这个对象

                 如果不存在,就在缓冲池中创建"test"这个对象,然后及那个"test"对象的引用地址返回给字符串常量str,str就会指向"test"字符串对象

                 如果存在,则不创建任何对象,直接将池中"test"的地址返回,赋值给字符串常量,共创建了1个对象。

            2 对于s2 ,在创建时,同样会先查询缓冲池,因为缓存池中存在,所以直接将池中的地址返回,赋值给字符串常量,共创建了0个对象。

            3 对于s3,在创建时,同样会先查询缓冲池,因为存在test对象,所以不必创建,然后test对象作为构造函数的对象,在内存中(非缓存池)又创建了一个新的字符串对象,共创建了1个对象。

            4 s4 的创建过程同s3

            5 在创建时,同样会先查询缓冲池,缓存池中不存在test2对象,先创建一个test2字符串对象,然后再以test2为构造函数参数创建一个s5对象,共创建了2个对象。

    String str1="java";
    String str2="blog"; 
    String s_1=str1+str2;
    String s_2=str1+ "blog";
    String s_3="java"+"blog"; 
    System.out.print(s_1 == s_2);
    System.out.print(s_1 == s_3);
    System.out.println(s_2 == s_3);
    System.out.print(s_1=="javablog");
    System.out.print(s_2=="javablog");
    System.out.println(s_3=="javablog");

         结果:

            false false false

            false false true

        解析:

           1. s_1 创建时,+运算符会先在堆中创建两个对象str1、 str2,会在缓冲池直接复制给这两个值,然后运行时创建一个StringBuilder并用str1 的字符串完成初始化,然后调用append方法合并str2的字符串,最后使用toString方法完成类型转换,形成新对象引用给s_1,共创建了3个对象。

           2. s_2 创建时,不放入字符串池中,在堆中先创建对象str1,然后再查找缓冲池,存在"java"对象,直接引用,,然后运行时创建一个StringBuilder并用str1 的字符串完成初始化,然后调用append方法合并"blog"。最后使用toString方法完成类型转换,形成新对象引用给s_1,共创建2个对象。

           3. s_3 创建时,会直接查询缓冲池,存在,则赋值,不存在再创建,所以此过程共创建1个对象。

       总结:

           1.  ""引号创建的字符串会在字符串池中。

           2. new 创建的会先查看池中有相同的值的字符串

                 如果有,则拷贝一份到堆中,然后返回堆中的地址;

                 如果没有,则直接在堆中创建一份,然后返回堆中的地址(此时不需要在堆中复制到池中,否则,会浪费池的空间)

       c) String StringBuffer StringBuilder

           1 区别

             a) String:不可变字符;

                 StringBuffer:可变字符序列、效率低、线程安全(操作方法上加synchronized);

                 StringBuilder:可变字符序列、效率高、线程不安全;

            b)String可以赋予空值,后两个不行

          2 总结

              a) 操作少量数据使用String;

              b) 多线程下操作大量数据使用StringBuffer;

              c) 单线程下操作大量数据使用StringBuilder(推荐使用);

         3 速度排序:String < StringBuffer < StringBuilder

    String s = "aaa";
    long l1 = System.currentTimeMillis();
    for(int i = 0;i<100000;i++) {
        s+=i;
    }
    long l2 = System.currentTimeMillis();
    System.out.println(l2-l1);
	    
    s="aaa";
    StringBuffer s2 = new StringBuffer(s);
    long l3 = System.currentTimeMillis();
    for(int i = 0;i<10000000;i++) {
        s2.append(i);
    }
    long l4 = System.currentTimeMillis();
    System.out.println(l4-l3);
	    
    s="aaa";
    StringBuilder s3 = new StringBuilder(s);
    long l5 = System.currentTimeMillis();
    for(int i = 0;i<10000000;i++) {
        s3.append(i);
    }
    long l6 = System.currentTimeMillis();
    System.out.println(l6-l5);

        结果:

                27951

                433

                310

        结论:

            可以看出,在StringBuffer 和StringBuilder 是String拼接次数的100的情况下,还快100倍。

            原因在每次String对于字符串拼接的时候都会创建一个StringBuilder 使用append方法拼接完之后,再用toString()方法再转换成String类。执行次数越多,创建和销毁的对象就越多。

       

你可能感兴趣的:(JavaSE基础,Java,String类)