首页 > 编程语言 >【面试精讲】String是如何实现的?String源码分析

【面试精讲】String是如何实现的?String源码分析

时间:2024-03-17 12:58:42浏览次数:23  
标签:Java String int 精讲 value 源码 字符串

【面试精讲】String是如何实现的?String源码分析

目录

一、String实现机制

二、String不可变性(使用final修饰)

三、String 和 StringBuilder、StringBuffer 的区别

四、==和equals的区别

五、String创建对象与JVM辨析

六、String源码解析

1、compareTo()

2、 equals() 

总结

 博主v:XiaoMing_Java


在Java中,String类是使用最频繁的类之一。由于其不可变性、效率以及如何影响内存使用等方面的特点,String类成为了Java编程语言的一个核心组成部分。本文深入探讨String的实现机制、它的源码结构、特点以及用final修饰的好处。

一、String实现机制

在Java中,String被设计为不可变(immutable)的对象。这意味着一旦String对象被创建,它所包含的字符序列就不能被修改。每次对字符串进行操作时(例如拼接、替换字符等),实际上都会创建一个新的String对象。

从JDK 1.0到JDK 8,String内部是通过一个char数组来实现的,保存着所有的字符数据。从JDK 9开始,String类的内部实现改为使用byte数组加上一个编码标记(coder),以更有效地处理不同的字符集,优化内存使用和性能。

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
    // 用于存储字符串的值
    private final char value[];

    // 缓存字符串的 hash code
    private int hash; // Default to 0
}

自JDK 9起,为了提升空间效率和性能,String的内部表示发生了变化,使用byte数组加上一个编码标志字段coder来存储字符串,如下所示:

// JDK 9及以后的String内部结构
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
    // 实际存储字符串内容的byte数组
    private final byte[] value;

    // 字符串使用的编码标识(用于区分使用Latin-1还是UTF-16编码)
    private final byte coder;

    // 缓存字符串的哈希码
    private int hash; // 默认为0

    // 构造方法之一,用于从字符数组初始化字符串
    public String(char[] value) {
        // 这里简化了实际的实现细节
        this.value = StringLatin1.toBytes(value);
        this.coder = LATIN1;
    }

    // length() 方法实现
    public int length() {
        return value.length >> coder;
    }
}

二、String不可变性(使用final修饰)

String对象一旦被创建,其内容就不能被改变。任何对String的修改操作都会导致新的String对象的生成。这个特性带来了以下好处:

安全性:String常作为参数传递,其不可变性保证了数据不会被意外改变。防止子类改变父类(String)的行为,确保所有String实例都具有String定义的行为。

线程安全:在多线程环境下,String可以被自由共享而无需同步控制。

高效:因为String的内容不变,所以其哈希码可以被缓存,提高哈希表操作的效率。性能优化:

简化设计:由于不需要考虑子类的影响,使得String类的设计更简单、更稳定

 

三、String 和 StringBuilder、StringBuffer 的区别

String类重载了+运算符,使得字符串连接操作非常方便。然而,频繁的字符串连接操作会产生大量临时字符串对象,影响性能。为了解决这个问题,Java引入了StringBuilderStringBuffer两个类,它们允许在单个字符序列上执行可变操作。

因为 String 类型是不可变的,所以在字符串拼接的时候如果使用 String 的话性能会很低,因此我们就需要使用另一个数据类型 StringBuffer,它提供了 append 和 insert 方法可用于字符串的拼接,它使用 synchronized 来保证线程安全。

在 JDK 1.5 有了 StringBuilder,它同样提供了 append 和 insert 的拼接方法,在非并发操作的环境下可使用 StringBuilder 来进行字符串拼接。

四、==和equals的区别

== 对于基本数据类型来说,是用于比较 “值”是否相等的;而对于引用类型来说,是用于比较引用地址是否相同的。

// Object 中的 equals() 方法其实就是 ==
public boolean equals(Object obj) {
    return (this == obj);
}

// 而String重写equals()方法把它修改成比较两个字符串的值是否相等
public boolean equals(Object anObject) {
    // 对象引用相同直接返回 true
    if (this == anObject) {
        return true;
    }

    // 判断需要对比的值是否为 String 类型,如果不是则直接返回 false
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {

            // 把两个字符串都转换为 char 数组对比
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;

            // 循环比对两个字符串的每一个字符
            while (n-- != 0) {

                // 如果其中有一个字符不相等就 true false,否则继续对比
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

五、String创建对象与JVM辨析

String 常见的创建方式有两种,new String() 的方式和直接赋值的方式

直接赋值的方式会先去字符串常量池中查找是否已经有此值,如果有则把引用地址直接指向此值,否则会先在常量池中创建,然后再把引用指向此值;

new String() 的方式一定会先在堆上创建一个字符串对象,然后再去常量池中查询此字符串的值是否已经存在,如果不存在会先在常量池中创建此字符串,然后把引用的值指向此字符串

JDK 1.7 之后把永生代换成的元空间,把字符串常量池从方法区移到了 Java 堆上。

六、String源码解析

1、compareTo()

public int compareTo(String anotherString) {
    int len1 = value.length;
    int len2 = anotherString.value.length;

    // 获取到两个字符串长度最短的那个 int 值
    int lim = Math.min(len1, len2);
    char v1[] = value;
    char v2[] = anotherString.value;
    int k = 0;

    // 对比每一个字符
    while (k < lim) {
        char c1 = v1[k];
        char c2 = v2[k];
        if (c1 != c2) {
            // 有字符不相等就返回差值
            return c1 - c2;
        }
        k++;
    }
    return len1 - len2;
}

2、 equals() 

public boolean equals(Object anObject) {
    // 对象引用相同直接返回 true
    if (this == anObject) {
        return true;
    }

    // 判断需要对比的值是否为 String 类型,如果不是则直接返回 false
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {

            // 把两个字符串都转换为 char 数组对比
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;

            // 循环比对两个字符串的每一个字符
            while (n-- != 0) {
                // 如果其中有一个字符不相等就 true false,否则继续对比
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

总结

String在Java中的地位极其重要,其设计精巧、使用广泛。通过不可变性设计,String提供了高度的安全性和线程安全,同时final修饰符进一步确保了其不变契约的稳定性。了解String的内部实现和特点对于写出高效、安全和易维护的Java代码至关重要。

Java开发者应当熟练掌握String的使用,并在合适的场景选择使用StringBuilderStringBuffer以优化性能。此外,深入理解String的设计哲学也有助于开发者设计自己的不可变类,为构建稳定和高效的Java应用打下坚实的基础。

如果本文对你有帮助 欢迎 关注 、点赞 、收藏 、评论, 博主才有动力持续记录遇到的问题!!!

 博主v:XiaoMing_Java

  

标签:Java,String,int,精讲,value,源码,字符串
From: https://blog.csdn.net/FMC_WBL/article/details/136695096

相关文章

  • java毕设安卓昆虫科普APP实现(开题+源码)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着移动互联网的普及和智能手机的广泛应用,人们的生活方式发生了深刻变革。智能手机APP以其便捷性、交互性和个性化等特点,成为现代人获取信息和知识......
  • java毕设安卓考研院校择选app(开题+源码)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在数字化快速发展的时代,信息技术的应用已深入到各个领域,教育行业亦不例外。特别是在考研这一重要的人生节点上,学生们面临着院校选择、专业匹配、分数......
  • FFmpeg开发笔记(六)如何访问Github下载FFmpeg源码
    ​学习FFmpeg的时候,经常要到GitHub下载各种开源代码,比如FFmpeg的源码页面位于https://github.com/FFmpeg/FFmpeg。然而国内访问GitHub很不稳定,经常打不开该网站,比如在命令行执行下面的ping命令。pinggithub.com上面的ping结果如下所示,可见默认解析的DNS地址连接超时。正在......
  • UVA10829 L-Gap Substrings
    我永远喜欢数据结构。貌似是此题中第一个使用SA+分治+二维数点做法的题解?题目传送门给出字符串\(s\)和常数\(g\),求出有多少四元组\((l_1,r_1,l_2,r_2)\),满足\(s[l_1,r_1]=s[l_2,r_2]\)且\(r_1+g+1=l_2\)。\(T\)组数据,\(1\leT,g\le10\),\(|s|\le5\times10......
  • java毕设安卓禁毒宣传APP(开题+源码)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在当今社会,禁毒工作面临着前所未有的挑战。随着互联网的普及,毒品信息传播的速度和范围不断扩大,对青少年和社会造成了极大的危害。因此,加强禁毒宣传教......
  • java毕设安卓教务的校内人员疫情排查APP(开题+源码)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在新冠疫情全球蔓延的背景下,校园作为人员密集场所,疫情防控工作显得尤为重要。特别是在高校中,由于学生、教师流动性大,信息沟通不畅,疫情排查工作面临着......
  • 【Qt】使用Qt实现Web服务器(二):QtWebApp示例源码
    1、最简使用介绍Demo2演示了最简单的用法,输入url后返回“HelloWorld!”;下面详解示例代码,先看主函数1.1主函数#a)QtWebApp库中定义的名字空间stefanfringsusingnamespacestefanfrings;intmain(intargc,char*argv[]){......
  • django重庆工商大学校园车辆管理系统(源码+mysql+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取本课题的源码和程序系统程序文件列表系统的选题背景和意义选题背景:随着科技的不断发展,信息化已经成为了现代社会的一种趋势。在校园中,车辆管理作为一项重要的工作,其效率和准确性对于保障校园安全和秩序具有重要意义。重庆工......
  • django中医共享管理系统设计(源码+mysql+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取本课题的源码和程序系统程序文件列表系统的选题背景和意义选题背景:随着科技的发展,互联网技术已经深入到各个领域,医疗行业也不例外。中医作为中国传统的医学,其独特的诊疗方式和理论体系在全世界都有一定的影响力。然而,中医的......
  • 无需服务器的短视频去水印源码
    源码介绍:无需服务器的短视频去水印,真正的永久去水印小程序源码~搭建教程:1、导入开发者工具2、全局搜索:解析接口3、替换解析接口后即可~源码获取方式 回复:0312即可获取......