【我与Java的成长记】之String类详解

马肤
这是懒羊羊

【我与Java的成长记】之String类详解,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,没有,li,第1张

系列文章目录

能看懂文字就能明白系列

C语言笔记传送门

Java笔记传送门

🌟 个人主页:古德猫宁-

🌈 信念如阳光,照亮前行的每一步


文章目录

  • 系列文章目录
    • 🌈 *信念如阳光,照亮前行的每一步*
    • 前言
    • 一、字符串构造
    • 二、String类的特性
    • 三、StringBuilder和StringBuffer
      • 总结
      • 三、StringBuilder一些常见的方法

        前言

        String 类是 Java 中用于表示字符串的核心类之一。它提供了丰富的方法来操作字符串,包括连接、拆分、替换、查找、截取等,使得字符串处理变得简单和高效。

        本节重点:

        • 理解String为什么具有不可变性
        • StringBuffer、StringBuilder和String的区别
        • 为什么StringBuilder比StringBuffer总是快了一毫秒
        • 模拟简单String类方法的实现

          一、字符串构造

          常用的字符串构造有以下三种:

          public static void main(String[] args) {
                  //new一个String对象
                  String s1 = new String("hello");
                  
                  //使用常量串进行构造
                  String s2 = "hello";
                  
                  //使用字符数组进行构造
                  char[] arr = {'h','e','l','l','o'};
                  String s3 = new String(arr);
              }
          

          在这里特别注意的是:

          1. s1,s2,s3存储的是一个地址,由地址指向所引用的对象,可是当我们打印s1,s2,s3的时候,却发现输出的结果是“hello”

            【我与Java的成长记】之String类详解,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,没有,li,第2张

            原因是String调用了toString的构造方法,我们打开String的源码看看

            【我与Java的成长记】之String类详解,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,没有,li,第3张

            【我与Java的成长记】之String类详解,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,没有,li,第4张

            【我与Java的成长记】之String类详解,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,没有,li,第5张

            最后是print输出“hello”。

          2. String类是引用类型,内部并不存储字符串本身,在String类的实现源码中,String类实例变量如下:

            【我与Java的成长记】之String类详解,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,没有,li,第6张

            我们可以看到,String类中有两个成员,一个是数组value[],一个是整型hash(默认为0),当我们调试的时候,我们可以看到是value[]存储的“hello”

            【我与Java的成长记】之String类详解,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,没有,li,第7张

            如下图所示,我们可以这样理解:

            【我与Java的成长记】之String类详解,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,没有,li,第8张

          3. 字符串常量后面没有以\0标记结尾,我们可以调用length看下字符串的长度。

            【我与Java的成长记】之String类详解,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,没有,li,第9张

            【我与Java的成长记】之String类详解,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,没有,li,第10张

          二、String类的特性

          String 对象具有不可变性的,即一旦创建就不能被修改。这种不可变性使得字符串在多线程环境下更安全,也可以被用作常量,有助于提高代码的可读性和可维护性。

          我们先来看以下代码:

          public static void main(String[] args) {
                  String s = "hello";
                  s = s.concat(" java");
                  System.out.println(s);
              }
          

          输出结果:

          【我与Java的成长记】之String类详解,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,没有,li,第11张

          这里很多人可能就有疑问了,不是说String对象具有不可变性吗,为什么这里还可以被改变呢?

          虽然字符串的内容看起来变了,从“hello”变成了“hello java”,但实际上,原来的字符串还是没有改变,而是得到了一个新的字符串了,它的内容是“hello java”。

          具体如图所示:

          【我与Java的成长记】之String类详解,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,没有,li,第12张

          为什么字符串具有不可变性呢?

          一方面,String类中的字符实际保存在内部维护的value字符数组中,另一方面,String类被final修饰,表明该类不能被继承,而且value也被final修饰,表明value自身的值不能改变,既不能引用其他字符数组,但是其引用空间中的内容可以修改。

          特别注意的是:字符串不可变是因为其内部保存字符的数组被final修饰了,因此不能改变,这句话是错误的,不是因为String类自身,或者其内部value被final修饰而不能被修改。

          而是因为value[]被private修饰,我们无法拿到value,自然不能通过value去修改值。

          【我与Java的成长记】之String类详解,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,没有,li,第13张

          为什么String要设计成不可变的?

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

          三、StringBuilder和StringBuffer

          注意:尽量避免直接对String类型对象进行修改,因为String类是不能修改的,所有的修改都会创建新对象,效率非常低。

          所以为了方便字符串的修改,java中又提供了StringBuilder和StringBuffer类。

          StringBuffer和StringBuilder虽然也封装了一个字符数组,但与String不同,其定义如下:

          char[] value;

          与String不同的是,它并不是被final所修饰,所以是可以修改的。

          我们可以做个简单的测试:

          public static void main(String[] args) {
                  long start = System.currentTimeMillis();
                  String s = "";
                  for(int i = 0; i  
          

          【我与Java的成长记】之String类详解,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,没有,li,第14张

          从结果可以看出,在对String类进行修改时,效率是非常慢的,因此:尽量避免对String的直接修改,如果要修改尽量使用StringBuffer或者StringBuilder。

          注意:String和StringBuilder类不能直接转换。如果要想互相转换,可以采用如下原则:

          • String变为StringBuilder:利用StringBuilder的构造方法或者append()方法。
          • StringBuilder变为String:利用toString()方法。

            总结

            为什么StringBuilder和StringBuffer比String快那么多呢?

            简单来说String 是不可变的,每次对 String 进行操作(如连接、拼接、替换等),都会生成一个新的 String 对象,原始的 String 对象不变。这样会频繁地创建新的对象,产生大量的临时对象,导致内存开销和垃圾回收压力增大。

            StringBuffer 和 StringBuilder 是可变的,它们提供了修改字符串内容的方法,而不是创建新的对象。这样可以减少对象的创建和销毁,提高了性能。

            StringBuffer 和 StringBuilder 内部都是使用可变长度的字符数组(char[])来存储字符串内容。它们的方法都是基于字符数组的操作,如扩容、复制、移动等。这种直接操作字符数组的方式可以提高性能,避免了额外的对象创建和拷贝操作。

            为什么StringBuilder比StringBuffer总是快了一毫秒呢?

            原因是StringBuilder 是非线程安全的,而StringBuffer 是线程安全的,StringBuffer 中的方法是同步的,即它们被设计为可以安全地在多线程环境中使用。这是通过在每个方法上使用 synchronized 关键字来实现的,以确保同一时刻只有一个线程可以访问 StringBuffer 的方法。

            【我与Java的成长记】之String类详解,在这里插入图片描述,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,没有,li,第15张

            当方法被 synchronized 修饰时,就意味着该方法在同一时间只能被一个线程执行,其他线程需要等待。

            三、StringBuilder一些常见的方法

            由于StringBuilder和StringBuffer两大类大部分功能是相同的,这里简单介绍StringBuilder一些常用的方法,其他方法可自行浏览:StringBuilder在线文档

            方法说明
            StringBuilder append(String str)在尾部追加,相当于String的+=,可以追加:boolean,char,char[],double,float,int,long,Object,String,StringBuilder的变量
            char charAt(int index)获取index位置的字符
            int length()获取字符串的长度
            int capacity()获取底层保存字符串空间总的大小
            void ensureCapacity(int mininmunCapacity)扩容
            void setChar(int index,char ch)将index位置的字符设置为ch
            int indexOf(String str)返回str第一次出现的位置
            int indexOf(String str,int fromIndex)从fromIndex位置开始查找str第一次出现的位置
            StringBuffer deleteCharAt(int index)删除index位置的字符
            StringBuffer delete(int start,int end)删除[start,end)区间内的字符
            StringBuffer replace(int start,int end,String str)将[start,end)位置的字符替换为str
            String substring(int start)从star开始一直到末尾的字符以String的形式返回
            StringBuffer reverse()反转字符串


文章版权声明:除非注明,否则均为VPS857原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复:表情:
评论列表 (暂无评论,0人围观)

还没有评论,来说两句吧...

目录[+]

取消
微信二维码
微信二维码
支付宝二维码