• 浅挖一下String类,解决String常见的面试题


    详解Java中的String类

    1. String 是 Java 基本数据类型吗?

    许多同学在学习String类时,会误认为String类是基本数据类型,因为实实在在好像有点像C语言中的字符数组,字符,那不就是基本数据类型吗?可实际上不是的.在Java中String是个表示字符串的一个类,它是由字符组成的不可变序列。尽管String在使用时表现得像基本数据类型,但它实际上是一个引用数据类型.
    补充: Java中基本数据类型为byte(1字节),short(2字节),int(4字节),long(8字节),float(4字节),double(8字节),char(2字节),boolean(不固定)

    需要注意的是,虽然boolean类型在逻辑上可能只占用1位,但在实际的内存存储中,JVM可能会为其分配更多的空间(例如,在数组中,每个boolean元素可能会占用一个字节)

    2. String类可以被继承吗?

    答案是否定的,我们去看看String的源码在这里插入图片描述
    发现String类是被final修饰的,所以是不可继承的.

    补充: final可修饰变量,方法,类

    • final修饰变量时,表示为常量,被final修饰的变量必须赋初值
    • final修饰方法时,表明这个方法不可被重写.
    • final修饰类时,表明这个类不可被继承.

    这种设计主要是由于这几个原因:

    • 字符串的不可变性:String类的不可变性使得它可以被安全地用于多线程环境下,不会出现线程安全问题。
    • 字符串常量池的优化:由于字符串是不可变的,Java可以对字符串进行缓存和共享,以提高性能和节省内存。这就是通过字符串常量池来实现的,它存储了所有字符串字面量的唯一实例。
    • 安全性和可靠性:String类的不可变性使得它在安全性和可靠性方面更加可靠。例如,它可以被用作Map的键,因为它的哈希值是固定的

    3. new一个String类和直接赋值一个字符串有什么区别啊?

    我们来看下面这一串代码,思考会有什么样的区别呢?
    在这里插入图片描述

    两个语句都会去字符串常量池中检查是否已经存在 “abc”,如果有则直接使用,如果没有则会在常量池中创建 “abc” 对象

    在这里插入图片描述
    但是不同的是,String str1 = new String(“abc”) 还会通过 new String() 在堆里创建一个 “abc” 字符串对象实例。所以后者可以理解为被前者包含。

    String s = new String(“abc”)创建了几个对象?很明显,一个或两个。如果字符串常量池已经有“abc”,则是一个;否则,两个。

    当字符创常量池没有 “abc”,此时会创建如下两个对象:

    • 一个是字符串字面量 “abc” 所对应的、字符串常量池中的实例
    • 另一个是通过 new String() 创建并初始化的,内容与"abc"相同的实例,在堆中

    4.String不是不可变类吗?字符串拼接是如何实现的?

    String的确是不可变的,“+”的拼接操作,其实是会生成新的对象。

    例如这段代码:
    在这里插入图片描述
    在jdk1.8之前,a和b初始化时位于字符串常量池,ab拼接后的对象位于堆中。经过拼接新生成了String对象。如果拼接多次,那么会生成多个中间对象

    而在Java8以后,JDK对“+”号拼接进行了优化,上面所写的拼接方式会被优化为基于StringBuilder的append方法进行处理。Java会在编译期对“+”号进行处理。

    所以,通过加号拼接字符串会创建多个String对象,因此性能比StringBuilder差,就是错误的了。因为本质上加号拼接的效果最终经过编译器处理之后和StringBuilder是一致的

    5.intern方法有什么作用?

    源码中用英文解释了
    在这里插入图片描述
    大致意思为

    • 如果当前字符串内容存在于字符串常量池(即equals()方法为true,也就是内容一样),直接返回字符串常量池中的字符串
    • 否则,将此String对象添加到池中并返回String对象的引用

    6.String 和 StringBuilder,StringBuffer?

    在这里插入图片描述

    1. String类:String是不可变的,使用 private final char value[] 来存储字符串,一旦创建就不能修改其值。任何对String的修改都会创建一个新的String对象。String类是线程安全的,因为它的不可变性保证了多个线程可以安全地共享String对象。然而,由于不可变性的特性,对于频繁的字符串拼接操作,会产生大量的临时对象,影响性能。
    2. StringBuffer类:StringBuffer是可变的,使用 char value[] 存储字符串,它的值可以被修改。为了保证线程安全性,StringBuffer的方法都使用synchronized关键字进行同步。因此,在多线程环境下,使用StringBuffer可以保证线程安全。然而,由于同步的开销,StringBuffer的性能相对较低
    3. StringBuilder类:StringBuilder是StringBuffer的非线程安全版本,它的方法没有使用synchronized关键字进行同步。因此,在单线程环境下,使用StringBuilder可以获得更好的性能。然而,由于不具备线程安全性,如果在多线程环境下使用StringBuilder,需要自行保证线程安全

    一般来说,在实际使用中:如果操作的数据量较小,可以使用String类。如果在多线程环境下操作大量的数据,需要保证线程安全,可以使用StringBuffer类。如果在单线程环境下操作大量的数据,可以使用StringBuilder类以,性能更好。

  • 相关阅读:
    Clion常用插件
    Python性能优化实录
    C++20之Module(浅析)
    智能网联汽车云控系统第5部分:平台服务场景规范
    C/C++好用的websocket库
    使用Dask,SBERT SPECTRE和Milvus构建自己的ARXIV论文相似性搜索引擎
    Debian 12安装Docker
    [计算机网络]-网络层-概述及虚电路和数据报网络
    软件测试面试题 —— 整理与解析(3)
    引入Bootstrap的CSS样式后,<h>标签、<p>标签等HTML自带的标签被覆写没有?答:覆写了。
  • 原文地址:https://blog.csdn.net/m0_65013257/article/details/139755467