String的不可变性

简介: String的不可变性

概述

String类的不可变性意味着一旦创建了一个字符串对象,它的值就不能被修改。

String是如何实现不可变的

查看源码

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
    // 字符数组value用于存储字符序列
    private final char value[];
 
    // substring方法返回一个新的String对象
    public String substring(int beginIndex) {
        if (beginIndex < 0 || beginIndex > value.length) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        int subLen = value.length - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
    }
 
    // concat方法用于连接字符串并返回一个新的String对象
    public String concat(String str) {
        int otherLen = str.length();
        if (otherLen == 0) {
            return this;
        }
        int len = value.length;
        char buf[] = Arrays.copyOf(value, len + otherLen);
        str.getChars(buf, len);
        return new String(buf, true);
    }
}

1.String类被声明为final,这意味着它不能被继承。那么他里面的方法就是没办法被覆盖的。

2.用final修饰字符串内容的char[] (从JDK 1.9开始,char[]变成了byte[]),由于该数组被声明为final,一旦数组被初始化,就不能再指向其他数组

3.String类没有提供用于修改字符串内容的公共方法。例如,没有提供用于追加、删除或修改字符的方法。如果需要对字符串进行修改,会创建一个新的String对象。

String为何设计成不可变的

为什么要把String设计成不可变的呢? 有什么好处呢?

这个问题,困扰过很多人,甚至有人直接问过Java的创始人James Gosling。

在一次采访中James Gosling被问到什么时候应该使用不可变变量,他给出的回答是:

I would use an immutable whenever I can(我会尽可能使用不可变的。)

那么,他给出这个答案背后的原因是什么呢? 是基于哪些思考的呢?

其实,主要是从缓存、安全性、线程安全和性能等角度出发的。

1.缓存和性能优化

字符串是使用最广泛的数据结构。大量的字符串的创建是非常耗费资源的,所以,Java提供了对字符串的缓存功能,可以大大的节省堆空间。

JVM中专门开辟了一部分空间来存储Java字符串,那就是字符串池

通过字符串池,两个内容相同的字符串变量,可以从池中指向同一个字符串对象,从而节省了关键的内存资源。

String s="abcd";
String s2=s1;

对于这个例子,s和s2都表示"abcd",所以他们会指向字符串池中的同一个字符串对象.

但是,之所以可以这么做,主要是因为字符串的不变性。试想一下,如果字符串是可变的,我们一旦修改了s的内容,那必然导致s2的内容也被动的改变了,这显然不是我们想看到的。

缓存HashCode。由于字符串的不可变性,可以将字符串的哈希码(HashCode)缓存起来,这样在多次使用字符串的哈希码时就不需要重新计算,提高了性能。

2.安全性

String对象在Java中广泛用于存储敏感信息,例如密码、数据库连接等。如果String是可变的,那么它的值可以被修改,这可能导致潜在的安全漏洞。通过将String设计为不可变的,可以确保其值在创建后不能被修改,提高了数据的安全性。

3.线程安全性

不可变会自动使字符串成为线程安全的,因为当从多个线程访问它们时,它们不会被更改。

因此,一般来说,不可变对象可以在同时运行的多个线程之间共享。它们也是线程安全的,因为如果线程更改了值,那么将在字符串池中创建一个新的字符串,而不是修改相同的值。因此,字符串对于多线程来说是安全的。

4.API设计和预测性能

String的不可变性使得它的API设计更加简单和一致。在使用String时,我们可以放心地传递和接收String对象,不必担心它的值会被修改。此外,不可变性还使得String的哈希值和相等性判断可以预先计算,提高了这些操作的性能。

目录
相关文章
|
7月前
|
存储 缓存 安全
【Java】Java中String不可变性的底层实现
【Java】Java中String不可变性的底层实现
76 0
|
2月前
|
Java
【编程基础知识】(讲解+示例实战)方法参数的传递机制(值传递及地址传递)以及String类的对象的不可变性
本文深入探讨了Java中方法参数的传递机制,包括值传递和引用传递的区别,以及String类对象的不可变性。通过详细讲解和示例代码,帮助读者理解参数传递的内部原理,并掌握在实际编程中正确处理参数传递的方法。关键词:Java, 方法参数传递, 值传递, 引用传递, String不可变性。
68 1
【编程基础知识】(讲解+示例实战)方法参数的传递机制(值传递及地址传递)以及String类的对象的不可变性
|
关系型数据库 MySQL Java
记一次愚蠢的操作--String不可变性
记录一次在写代码时愚蠢的操作,本文涉及到的知识点:String不可变性
113 0
记一次愚蠢的操作--String不可变性
|
缓存 安全 Java
Java的string类常量池及不可变性
<div style="background-color:inherit"> <p style="margin-top:5px; margin-bottom:5px; background-color:inherit"><span style="background-color:rgb(255,255,0); line-height:1.5"><span style="font-size
3229 0
记一次愚蠢的经历--String不可变性
前言 只有光头才能变强。 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 记录一次在写代码时愚蠢的操作,本文涉及到的知识点:String不可变性 一、交代背景 我这边有一个系统,提供一个RPC接口去发送短信。
1137 0
|
Java 算法 缓存
java基础巩固-浅析String源码及其不可变性
字符串可以说是广泛应用在日常编程中,jdk从1.0就提供了String类来创建和操作字符串。同时它也是不可改变类(基本类型的包装类都不可改变)的典型代表。
1177 0
|
3月前
|
Java 索引
java基础(13)String类
本文介绍了Java中String类的多种操作方法,包括字符串拼接、获取长度、去除空格、替换、截取、分割、比较和查找字符等。
47 0
java基础(13)String类
|
28天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
49 2