• 字符串常量池与StringBuilder


    在这里插入图片描述

    一、字符串常量池

    public static void main(String[] args) {
            String s1 = "abc";
            String s2 = "abc";
            String s3 = new String("abc");
            String s4 = new String("abc");
            System.out.println(s1 == s2);
            System.out.println(s1 == s3);
            System.out.println(s3 == s4);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    上面两种创建String对象的方式相同吗?
    在这里插入图片描述
    在Java程序中,“ ”双引号引起来的字面类型的常量经常频繁使用,为了使程序的运行速度更快、更节省内存,Java为8种基本数据类型和String类都提供了常量池。

    1.使用字符常量直接赋值:

    public static void main(String[] args) {
            String s1 = "abc";
            String s2 = "abc";
            System.out.println(s1 == s2);
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    在直接用字面常量赋值String时,先在常量池里找,是否有这个字符串,如果没有则创建,我们发现常量池并没有abc,所以我们创建一个“abc”。
    在这里插入图片描述
    当第二次创建"abc"字符串赋给s2时直接指向就行.
    在这里插入图片描述
    s1和s2指向的是同一块引用,所以s1 == s2。
    2.通过new创建String类对象:
    在这里插入图片描述
    只要new对象,它的引用就是唯一的.
    使用常量串创建String类型对象的效率更高,而且更节省空间。
    3.intern方法:
    intern 是一个native方法(Native方法指:底层使用C++实现的,看不到其实现的源代码),该方法的作用是手动将创建的String对象添加到常量池中。

    public static void main(String[] args) {
            char[] ch = new char[]{'a','b','c'};
            String s1 = new String(ch);
            String s2 = "abc";
            System.out.println(s1 == s2);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述
    我们可见s1 和 s2指向不同的引用

    public static void main(String[] args) {
            char[] ch = new char[]{'a','b','c'};
            String s1 = new String(ch);
            s1.intern();
            String s2 = "abc";
            System.out.println(s1 == s2);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    intern()方法是将s1中的引用放入常量池中.当s2创建时,就会指向常量池的那个引用.
    在这里插入图片描述

    二、字符串的不可变性

    String是一种不可变对象. 字符串中的内容是不可改变。
    String的源码中,注解中写到String是一个常量,不可修改.
    在这里插入图片描述
    我们在来看String类型是如何存储字符串的
    在这里插入图片描述
    可能有人说因为被final修饰,所以不能修改,首先这是一个很大的误区,final修饰只能说明value引用的对象不能修改,而不是说value引用的值不能修改.
    在这里插入图片描述
    我们随便打开一个String的方法,这里打开的是toUpperCase方法,可以发现:所有涉及到修改字符串内容的方法都是创建一个新对象返回.
    String为什么要设计成不可变的?

    1. 方便实现字符串对象池. 如果 String 可变, 那么对象池就需要考虑写时拷贝的问题了.
    2. 不可变对象是线程安全的.
    3. 不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap 中.

    三、字符串修改

    字符串是不能修改的,每次修改都会创建新对象,效率非常低下.

    public static void main(String[] args) {
            String str = "wo"+"yao"+"jin"+"da"+"chang";
            System.out.println(str);
        }
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述
    当然是可以正常输出的,我们看一下汇编.
    在这里插入图片描述
    我们会发现创建了许多StringBuilder对象,去拼接字符串,这样效率十分低下。

    public static void main(String[] args) {
            long start = System.currentTimeMillis();
            String s = "";
            for(int i = 0; i < 10000; ++i){
                s += i;
            }
            long end = System.currentTimeMillis();
            System.out.println(end - start);
            start = System.currentTimeMillis();
            StringBuffer sbf = new StringBuffer("");
            for(int i = 0; i < 10000; ++i){
                sbf.append(i);
            }
            end = System.currentTimeMillis();
            System.out.println(end - start);
            start = System.currentTimeMillis();
            StringBuilder sbd = new StringBuilder();
            for(int i = 0; i < 10000; ++i){
                sbd.append(i);
            }
            end = System.currentTimeMillis();
    
            System.out.println(end - start);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在这里插入图片描述
    我们发现在对String进行修改时,String与StringBuffer和StringBuilder相差几百倍.

    四、StringBuilder与StringBuffer的方法

    在这里插入图片描述
    这里都是StringBuffer和StringBuilder的一些方法.
    1.append
    拼接字符串

    public static void main(String[] args) {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("wo yao jin da chang!");
            System.out.println(stringBuilder);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    2.reverse
    字符串逆置

    public static void main(String[] args) {
            StringBuilder stringBuilder = new StringBuilder("abcd");
            stringBuilder.reverse();
            System.out.println(stringBuilder);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    3.delete
    删除指定范围内的字符

    public static void main(String[] args) {
            StringBuilder stringBuilder = new StringBuilder("abcd");
            stringBuilder.delete(0,2);
            System.out.println(stringBuilder);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    String与StringBuilder相互转换:
    String和StringBuilder最大的区别在于String的内容无法修改,而StringBuilder的内容可
    以修改。频繁修改字符串的情况考虑使用StringBuilder
    1.String变为StringBuilder

    public static void main(String[] args) {
            //调用StringBuilder构造方法
            String str = "abc";
            StringBuilder stringBuilder = new StringBuilder(str);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
     public static void main(String[] args) {
            //append拼接字符串
            String str = "abc";
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(str);
            System.out.println(stringBuilder);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述
    1.StringBuilder变为String
    在这里插入图片描述
    我们可以看一下StringBuilder的toString()方法返回的是一个String对象.

    public static void main(String[] args) {
            //StringBuilder的toString()方法
            StringBuilder stringBuilder = new StringBuilder("abc");
            String str = stringBuilder.toString();
            System.out.println(str);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

    四、StringBuilder与StringBuffer区别

    String、StringBuffer、StringBuilder的区别:
    1.String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.
    2.StringBuffer与StringBuilder大部分功能是相似的
    3.StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作
    在这里插入图片描述
    StringBuffer中的每个方法加入了synchronized,它就相当于是一把锁,只要有第一个人访问这个方法,那么这个方法就只能等第一个人访问完成之后,剩下的人才能访问.

    String str = new String("abc"); 
    String str = new String("ab") + new String("c"); 
    
    • 1
    • 2

    这项行代码分别创建多少个对象?(之前常量池没有存储过任何字符串)

    1. 2个
    2. 6个
  • 相关阅读:
    数聚生态,智驭全界!看天翼云如何为智慧园区注入新动能!
    1017 A除以B【PAT (Basic Level) Practice (中文)】
    java基础05
    2024年【R1快开门式压力容器操作】模拟考试题及R1快开门式压力容器操作复审模拟考试
    EtcdServer初始化
    QT基础入门【QSS】继承、命名空间中的小部件、QObject 属性介绍
    chatgpt GPT-4V是如何实现语音对话的
    线程篇(JAVA)
    【Redis设计与实现】第一部分 :Redis数据结构和对象 总结
    混币器困境:保护了隐私也掩护了黑产
  • 原文地址:https://blog.csdn.net/buhuisuanfa/article/details/126706358