当前位置:
首页
文章
后端
详情

Java基础知识相关字符串String的详细内容总结

相信各位读者对于 Java 中的字符串类型 String 并不陌生,因为每次需要声明一个字符串变量,都需要用到 String 类型。但是对于 String 具体的、详细的内容知道不是很多,下面我将为大家详细地总结了关于 Java 中的字符串类型 String 的内容。

    一、前言

    字符串是多个字符连接起来组合成的字符序列。字符串分为可变的字符串和不可变的字符串两种。

    (1)不可变的字符串:当字符串对象创建完毕之后,该对象的内容(上述的字符序列)是不能改变的一旦内容改变就会创建一个新的字符串对象。Java中的String类的对象就是不可变的。

    (2)可变的字符串:StringBuilder类和StringBuffer类的对象就是可变的;当对象创建完毕之后,该对象的内容发生改变时不会创建新的对象,也就是说对象的内容可以发生改变,当对象的内容发生改变时,对象保持不变,还是同一个。

    2021051808452410

    String、StringBuffer、StringBuilder 都实现了 CharSequence 接口,字符串在底层其实就是char[],虽然它们都与字符串相关,但是其处理机制不同。

    二、String 类(字符串常量)

    String类表示不可变的字符串,当前String类对象创建完毕之后,该对象的内容(字符序列)是不变的,因为内容一旦改变就会创建一个一个新的对象。

    String 类是final类,不可以继承。对String类型最好的重用方式是组合而不是继承。

    2.1 String 类实例的创建

    方式一:通过字面量赋值创建,需要注意这里是双引号:"",区别与字符char类型的单引号:'';

    String s1 = "laofu";

    方式二:通过构造器创建;

    String s2 = new String(“laofu”);

    两种方式的区别:

    方式一:String s1 = “laofu”;

    有可能只创建一个String对象,也有可能创建不创建String对象;如果在常量池中已经存在”laofu”,那么对象s1会直接引用,不会创建新的String对象;否则,会先在常量池先创建常量”laofu”的内存空间,然后再引用。

    方式二:String s2 = new String(“laofu”);

    最多会创建两个String对象,最少创建一个String对象。可使用new关键字创建对象是会在堆空间创建内存区域,这是第一个对象;然后对象中的字符串字面量可能会创建第二个对象,而第二个对象如方式一中所描述的那样,是有可能会不被创建的,所以至少创建一个String个对象。

    2021051808452411

    上图中的常量池:用于存储常量的地方内存区域,位于方法区中。常量池又分为编译常量池和运行常量池两种:

    编译常量池:当把字节码加载进JVM的时候,其中存储的是字节码的相关信息(如:行号等)。

    运行常量池:其中存储的是代码中的常量数据。

    ① 使用字符串字面量创建的字符串,也就是单独使用""引号创建的字符串都是直接量,在编译期就会将其存储到常量池中;

    ② 使用new String("")创建的对象会存储到堆内存中,在运行期才创建;

    ③ 使用只包含直接量的字符串连接符如"aa" + "bb"创建的也是直接量,这样的字符串在编译期就能确定,所以也会存储到常量池中;

    ④ 使用包含String直接量的字符串表达式(如"aa" + s1)创建的对象是运行期才创建的,对象存储在堆中,因为其底层是创新了StringBuilder对象来实现拼接的;

    2.2 String 对象的比较

    ① 使用”==”号:用于比较对象引用的内存地址是否相同

    ② 使用equals方法:在Object类中和”==”号相同,但在自定义类中,建议覆盖equals方法去实现比较自己内容的细节;由于String类覆盖已经覆盖了equals方法,所以其比较的是字符串内容

    2.3 String对象的空值

    ① 对象引用为空, 此时s1没有初始化,也在JVM中没有分配内存空间。

    String s1 = null; 

    ② 对象内容为空字符串, 比如: 此时对象s2已经初始化,值为“”,JVM已经为其分配内存空间。

    String s2 = "";

    2.4 字符串拼接

    Java中的字符串可以通过是“+”实现拼接,那么代码中字符串拼接在JVM中又是如何处理的呢?我们通过一个例子说明:通过比较拼接字符串代码编译前后的代码来查看JVM对字符串拼接的处理。

    2021051808452412

    JVM会对字符串拼接做一些优化操作。

    ① 如果字符串字面量之间的拼接(如"aa" + “bb”),创建的也是直接量,这种情况在编译期就能确定,所以也会存储到常量池中

    ② 如果是对象之间拼接,或者是对象和字面量之间的拼接,亦或是方法执行结果参与拼接,String内部会使用StringBuilder先来获取对象的值,然后使用append方法来执行拼接。这种情况只能在运行期才能确定变量的值和方法的返回值。

    三、StringBuilder 与 StringBuffer(字符串变量)

    StringBuffer 和 StringBuilder都表示可变的字符串,两种的功能方法都是相同的。但唯一的区别:

    (1)StringBuffer:StringBuffer中的方法都使用了synchronized修饰符,表示同步操作,在多线程并发的时候可以保证线程安全,但在保证线程安全的时候,对其性能有一定影响,会降低其性能

    (2)StringBuilder:StringBuilder中的方法都没有使用了synchronized修饰符,线程不安全,正因为如此,其性能较高

    对并发安全没有很高要求的情况下,建议使用StringBuilder,因为其性能很高。

    四、String、StringBuilder 与 StringBuffer

    (1)由于 String 类的操作是产生新的 String 对象,而 StringBuilder 和 StringBuffer 只是一个字符数组的扩容而已,所以 String 类的操作要远慢于 StringBuffer 和 StringBuilder。

    大部分情况下:StringBuilder > StringBuffer > String

    String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象, 因此在每次对 String类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象。每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。

    而如果是使用 StringBuffer 类则结果就不一样了,每次结果都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,再改变对象引用。

    (2)使用选择

    使用 String 类的场景:在字符串不经常变化的场景中可以使用 String 类,例如常量的声明、少量的变量运算。

    使用 StringBuffer 类的场景:在频繁进行字符串运算(如拼接、替换、删除等),并且运行在多线程环境中,则可以考虑使用 StringBuffer,例如 XML 解析、HTTP 参数解析和封装。

    使用 StringBuilder 类的场景:在频繁进行字符串运算(如拼接、替换、和删除等),并且运行在单线程的环境中,则可以考虑使用 StringBuilder,如 SQL 语句的拼装、JSON 封装等。

    本篇关于 Java 基础知识之字符串 String 的知识总结的全部内容到此就介绍完了,想要了解更多关于 Java 字符串的其他内容,请搜索W3Cschool相关技术文章,也希望大家可以多多关注和支持我们!


    免责申明:本站发布的内容(图片、视频和文字)以转载和分享为主,文章观点不代表本站立场,如涉及侵权请联系站长邮箱:xbc-online@qq.com进行反馈,一经查实,将立刻删除涉嫌侵权内容。

    同类热门文章

    深入了解C++中的new操作符:使用具体实例学习

    C++中的new操作符是动态分配内存的主要手段之一。在程序运行时,我们可能需要动态地创建和销毁对象,而new就是为此提供了便利。但是,使用new也常常会引发一些问题,如内存泄漏、空指针等等。因此,本文将通过具体的示例,深入介绍C++中的new操作符,帮助读者更好地掌握其使用。

    
深入了解C++中的new操作符:使用具体实例学习

    怎么用Java反射获取包下所有类? 详细代码实例操作

    Java的反射机制就是在运行状态下,对于任何一个类,它能知道这个类的所有属性和方法;对于任何一个对象,都能调用这个对象的任意一个方法。本篇文章将通过具体的代码示例,展示如何通过Java反射来获取包下的所有类。

    
怎么用Java反射获取包下所有类? 详细代码实例操作

    了解Java中的volati关键字的作用 以及具体使用方法

    本篇文章将和大家分享一下Java当中的volatile关键字,下面将为各位小伙伴讲述volatile关键字的作用以及它的具体使用方法。

    
了解Java中的volati关键字的作用 以及具体使用方法

    Java Map 所有的值转为String类型

    可以使用 Java 8 中的 Map.replaceAll() 方法将所有的值转为 String 类型: 上面的代码会将 map 中所有的值都转为 String 类型。 HashMap 是 Java

    Java Map 所有的值转为String类型

    员工线上学习考试系统

    有点播,直播,在线支付,三级分销等功能,可以对学员学习情况的监督监控,有源码,可二次开发。支持外网和局域网私有化部署,经过测试源码完整可用!1、视频点播:视频播放,图文资料,课件下载,章节试学,限时免

    员工线上学习考试系统