36、Java 中的 String、StringBuilder、StringBuffer、字符串常量池和 intern 方法

这篇具有很好参考价值的文章主要介绍了36、Java 中的 String、StringBuilder、StringBuffer、字符串常量池和 intern 方法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、String

✏️ Java 中用 java.lang.String 类代表字符串
✏️ 底层用char[]存储字符数据。从 Java9 开始,底层使用 byte[]存储字符数据

36、Java 中的 String、StringBuilder、StringBuffer、字符串常量池和 intern 方法

public class TestDemo {
    public static void main(String[] args) {
        String bigBrother = "林哥"; // char[] value = {'林', '哥'};
    }
}

🌿 字符串的底层是 char[],但是 char 数组和字符串不能等价。char 数组是 char 数组,字符串是字符串。
🌿 C 语言中是可以把 char 数组和字符串等价的

✏️ 所有的 字符串字面量(如:"林哥")都是 String 类的实例
✏️ String 对象创建完毕后,String 对象的字符内容是不可以修改的

🌿 String 对象的引用变量的指向是可以修改的

public class TestDemo {
    public static void main(String[] args) {
        String s = "林哥";
        s += "love";
        s = "666";
        test(s);
        // s = 666
        System.out.println("s = " + s);
    }

    private static void test(String str) {
        // str 是局部变量, 生命周期只在 test 方法中
        str += 123;
    }
}

36、Java 中的 String、StringBuilder、StringBuffer、字符串常量池和 intern 方法

二、字符串常量池

✏️ 字符串常量池:String Constant Pool
✏️ 从 Java7 开始,字符串常量池是在空间(之前是在方法区)

🌿 当遇到字符串字面量的时候,会先在 SCP 中检索
🌿 看 SCP 中是否存在与字面量内容一样的字符串对象 A
🌿 如果有,返回字符串对象 A
🌿 否则,创建一个新的字符串对象 B,并将其加入到 SCP 中,然后返回 B

36、Java 中的 String、StringBuilder、StringBuffer、字符串常量池和 intern 方法

36、Java 中的 String、StringBuilder、StringBuffer、字符串常量池和 intern 方法

public class TestDemo {
    public static void main(String[] args) {
        String s1 = "林哥";
        String s2 = "林哥";
        // true
        System.out.println(s1 == s2);
    }
}

三、字符串的初始化

public class TestDemo {
    public static void main(String[] args) {
        String s1 = "林哥";
        String s2 = new String("林哥");
        // 字符串对象 s3 的值和字符串对象 s1 的值是一样的
        // 底层指向的都是同一个 char 数组
        String s3 = new String(s1);
        String s4 = new String(s2);

        char[] cs = {'林', '哥'};

        String s5 = new String(cs);
        String s6 = new String(s5);
    }
}

36、Java 中的 String、StringBuilder、StringBuffer、字符串常量池和 intern 方法


 String s1 = "林哥";
 String s2 = new String("林哥");

✏️ 上面的两行代码中,字符串对象 s1 底层的 char 数组 value 和字符串对象 s2 底层的 char 数组是同一个
✏️ 如下图所示:String 的构造方法会把传入的字符串对象的 value 直接赋值给当前对象(当前创建的新字符串对象)的 value
36、Java 中的 String、StringBuilder、StringBuffer、字符串常量池和 intern 方法

可通过 debug 的方式验证...

36、Java 中的 String、StringBuilder、StringBuffer、字符串常量池和 intern 方法

✏️ 上图:字符串对象 s1 底层的 value 的 id 号是 541
✏️ 字符串对象 s2 底层的 value 的 id 号也是 541

36、Java 中的 String、StringBuilder、StringBuffer、字符串常量池和 intern 方法

✏️ 给 String 对象的构造方法传入字符数组的时候,底层会拷贝一份该字符数组,然后才赋值给当前创建的 String 对象的 char 数组 value
36、Java 中的 String、StringBuilder、StringBuffer、字符串常量池和 intern 方法

四、String 类的 intern 方法

先看下面的代码,思考打印结果:

public class TestDemo {
    public static void main(String[] args) {
        String s0 = "林哥";
        String s1 = s0.intern();
        // true
        System.out.println(s1 == s0);

        String s2 = new String(s0);
        // false
        System.out.println(s2 == s0);

        String s3 = s2.intern();
        System.out.println(s3 == s0); // true
        System.out.println(s3 == s2); // false 
    }
}

36、Java 中的 String、StringBuilder、StringBuffer、字符串常量池和 intern 方法
36、Java 中的 String、StringBuilder、StringBuffer、字符串常量池和 intern 方法

✏️ 当字符串的 intern() 方法被调用的时候,如果字符串常量池中已经包含一个字符串对象的内容等于调用 intern()的字符串对象的内容,则返回字符串常量池中的字符串对象。否则,把调用 intern()的字符串对象添加到字符串常量池中,并返回该字符串对象(调用 intern()的字符串对象)

String s3 = s2.intern();

✏️ s2 调用了intern()方法,如果字符串常量池中存在与 s2 内容一样的字符串对象 s 的话,返回字符串常量池中的 s 对象;否则,将 s2 添加到字符串常量池中,并返回 s2


只有遇到字符串字面量的时候,才会在字符串常量池中检索

public class TestDemo {
    public static void main(String[] args) {
        int a = 1, b = 2, c = 3;
        String s1 = String.format("%d_%d_%d", a, b, c);
        String s2 = String.format("%d_%d_%d", a, b, c);
        System.out.println(s1 == s2); // output: false
        
        /*
            只有【字符串字面量】才会在字符串常量池中找检索
         */
    }
}
public class TestDemo {
    public static void main(String[] args) {
        int a = 1, b = 2, c = 3;
        String s1 = String.format("%d_%d_%d", a, b, c);
        String s2 = String.format("%d_%d_%d", a, b, c);
        System.out.println(s1 == s2); // output: false

        /*
            会把 s1 放入字符串常量池,并返回 s1 指向对象
            s3 和 s1 指向的是同一个对象
         */
        String s3 = s1.intern();

        /*
            会把被 s1 指向的字符串常量池中的字符串对象返回
            s1 和 s4 指向的是同一个对象
         */
        String s4 = s2.intern();

        /*
            返回字符串常量池中的字符串对象, 若 SCP 中没有, 创建一个放入 SCP, 并返回
         */
        String s5 = "1_2_3";

        System.out.println(s1 == s3); // true
        System.out.println(s1 == s4); // true
        System.out.println(s1 == s5); // true
    }
}

五、字符串常用方法

public class TestDemo {
    public static void main(String[] args) {
        // trim: 去除左右的空格
        String s1 = "  111 2222  ".trim();

        String s = "hAve A niCe Day";
        // toUpperCase: 把小写字母转为大写字母
        String s2 = s.toUpperCase();
        // toLowerCase: 把大写字母转换为小写字母
        String s3 = s.toLowerCase();

        // contains: 是否包含某个子字符串片段
        boolean contains = "Have a nice Day".contains("nice");

        // startsWith: 是否以某个子字符串片段开头
        boolean startsWith = "Love is love.".startsWith("love");

        // endsWith: 是否以某个子字符串片段结尾
        boolean endsWith = "Love is love".endsWith("love");

        // 将字符串分隔为字符串数组
        String[] split = "Today_we_have_a_new_student".split("_");
        // output: [Today, we, have, a, new, student]
        System.out.println(Arrays.toString(split));
    }
}

字符串的截取:

public class TestDemo {
    public static void main(String[] args) {
        String nice = "goodMorning";
        // 从下标 4 位置开始截取, 截取到最后
        String s1 = nice.substring(4);
        // output: s1 = Morning
        System.out.println("s1 = " + s1);

        String s = "believe";
        // 从下标 2 位置开始截取, 截取到下标为 5 的位置(不包括下标5位置的字符)
        // 左闭右开
        String s2 = s.substring(2, 5);
        // s2 = lie
        System.out.println("s2 = " + s2);
    }
}

indexOf: 定位字符串所在索引

public class TestDemo {
    public static void main(String[] args) {
        int result1 = "hello".indexOf("e");
        int result2 = "hello".indexOf("a");
        System.out.println(result1); // 1
        System.out.println(result2); // -1
    }
}

🌿 如果字符串中不包含该子字符串,返回 -1

lastIndexOf: 定位字符串所在索引

public class TestDemo {
    public static void main(String[] args) {
        // 从左往右开始定位字符串索引
        int result1 = "hello log".indexOf("lo");
        // 从右往左开始定位字符串索引(但数的时候还是从左往右数)
        int result2 = "hello log".lastIndexOf("lo");
        System.out.println(result1); // 3
        System.out.println(result2); // 6
    }
}

字符串替换:

public class TestDemo {
    public static void main(String[] args) {
        String s1 = "I live you";
        String s2 = s1.replace("live", "like");
        // s1 = I live you
        System.out.println("s1 = " + s1);
        // s2 = I like you
        System.out.println("s2 = " + s2);
    }
}

六、StringBuilder 和 StringBuffer

✒️ 需要进行大量的字符串改动操作(如拼接、替换)的时候,使用 String 会非常消耗内存、会降低程序性能
✒️StringBuilderStringBuffer 进行大量字符串拼接或替换的时候,程序性能和内存的消耗特别小

public class TestDemo {
    public static void main(String[] args) {
        String s = "1";
        s += "2";
        s += "3";
        s += "4";
        // s = 1234
        System.out.println("s = " + s);
    }
}

🌿 上面代码,每一次的拼接操作都会产生一个新的字符串对象

36、Java 中的 String、StringBuilder、StringBuffer、字符串常量池和 intern 方法

🌿 由于字符串内容的不可变性,每次的拼接操作必定都会产生一个新的字符串对象(如上图),会存在大量的字符串对象的创建和销毁操作


public class TestDemo {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("1");
        sb.append("2");
        sb.append("3");
        sb.append("4");
        // 1234
        System.out.println(sb.toString());

        // 链式调用
        StringBuffer sBuffer = new StringBuffer("1")
                .append("2")
                .append("3")
                .append("4");
        // 1234
        System.out.println(sBuffer);
    }
}

🌿 使用 StringBuilder 和 StringBuffer 则会非常高效
🌿 StringBuilder 和 StringBuffer 的使用方式(API)都一样
🌿 区别:StringBuilder 线程安全;StringBuffer 线程安全


✏️ 常用方法:append、insert、delete、replace、reverse
✏️ StringBuider 或 StringBuffer 与 String 并不存在继承关系
✏️ StringBuilder、StringBuffer、String 都实现了 CharSequence 接口

36、Java 中的 String、StringBuilder、StringBuffer、字符串常量池和 intern 方法

✏️ StringBuilder 的 append 原理:动态数组

动态数组的实现博主后期在学习,后期再写文章

结束,如有错误请不吝赐教文章来源地址https://www.toymoban.com/news/detail-405351.html

到了这里,关于36、Java 中的 String、StringBuilder、StringBuffer、字符串常量池和 intern 方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java基础09 —— 字符序列--String、StringBuilder、StringBuffer区别及其方法介绍

    字符与字符串 字符类型(char)是Java中的基本数据类型,占2个字节16位,默认值是 ‘u0000’ 。字符是用单引号引住的单个符号. 字符串(String)是用双引号引住的任意个字符,是引用数据类型,默认值是null 。字符串其实就是字符组成的序列 字符串声明 举例: 字符序列 多个字符

    2024年02月09日
    浏览(24)
  • java中的String使用注意事项、StringBuilder、StringBuffer、StringJoiner

    String使用注意事项 这里第二次创造了0个对象是因为字符串常量池中已经有\\\"abc\\\" StringBuilder 注意StringBuilder支持链式编程 StringBuilder 线程安全与不安全的区别在于,当系统里存在很多人同时操作同一个StringBuilder就可能出bug,而StringBuilder不会。 StringJoiner

    2024年02月12日
    浏览(23)
  • 【Java基础教程】(三十三)常用类库篇 · 第三讲:可变字符串支持类——解析 StringBuffer与 StringBuilder类~

    在Java 中,字符串使用 String 类进行表示,但是 String 类所表示的字符串有一个最大的问题:“字符串常量一旦声明则不可改变,而字符串对象可以改变,但是 改变的是其内存地址的指向”。所以 String 类不适合于被频繁修改的字符串操作, 所以在这种情况下,往往可以使用

    2024年02月15日
    浏览(25)
  • java基础四-String/StringBuffer/StringBuilder区别

    String 和 StringBuffer、StringBuilder 的区别在于 String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象,而 StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。 StringBuffer 和

    2024年02月14日
    浏览(28)
  • 【java】关于String、StringBuffer和StringBuilder的那些事

      目录 一、String 1、构造方法 2、字符串的不可变性 3、字符串的比较 4、 String的常用方法: 二、StringBuider和StringBuffer 1、字符串的拼接 2、StringBuider与StringBuffer 总结     String类提供的构造方式非常多,常用的就以下两种:   注意: 1、String 是引用类型,内部并不存储字符串

    2024年04月10日
    浏览(23)
  • 【JAVA】String ,StringBuffer 和 StringBuilder 三者有何联系?

    个人主页:【😊个人主页】 系列专栏:【❤️初识JAVA】 在之前的文章中我们介绍了JAVA中String的运用方法,事实上在JAVA字符串操作中仅仅只知道String方法是远远不够的,今天我们要介绍的 StringBuffer 和 StringBuilder 在字符串操作中同样占据总要地位。 和 String 类不同的是,S

    2024年02月14日
    浏览(26)
  • 【后端面经-Java】String与StringBuffer与StringBuilder的比较

    目录 1. String 2. StringBuffer 3. StringBuilder 4. 性能提升 5. 总结和比较 面试模拟 参考资料 不可变 查看 String 源码如下:由源码可知,String中存储数据的数组被 final 修饰,因此是不可变的 运算和操作 创建对象 创建对象有两种方式:两种方式都会在栈中创建一个字符串变量

    2024年02月16日
    浏览(29)
  • Java-String、StringBuffer、StringBuilder区别及相关面试题

    在Java编程中,经常会遇到处理字符串的需求。Java提供了多个类来处理字符串,其中最常用的是String、StringBuffer和StringBuilder类。本文将介绍这三个类的基本用法和区别。 String是Java中最常用的字符串类,它是不可变的,也就是说一旦被创建,它的值就不能被改变。下面是Stri

    2024年02月11日
    浏览(27)
  • StringBuilder > StringBuffer > String

    StringBuilder , StringBuffer 和 String 都是 Java 中用于操作字符串的类,但它们在性能、线程安全性和用途上有一些区别。 1. String: String 类是 Java 中的不可变字符串类。一旦创建了字符串对象,它的值就不能被修改。每次对字符串进行操作(连接、替换等),都会创建一个新的字符

    2024年02月11日
    浏览(29)
  • String、StringBuffer、StringBuilder 的区别?

    一. 介绍 String、StringBuffer、StringBuilder:    前言: String、StringBuffer、StringBuilder 均在java.lang包下; String:  在Java中,String是一个特殊的引用类型,用于表示文本字符串。它提供了许多方法来操作和处理字符串,比如连接、截取、查找、替换等。 String类内部使用字符数组(ch

    2024年02月13日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包