String真的不可变吗?
Java中的String是不可变对象
在面向对象及函数编程语言中,不可变对象(英语:Immutable object)是一种对象,在被创造之后,它的状态就不可以被改变。至于状态可以被改变的对象,则被称为可变对象(英语:mutable object)。-- 来自百度百科
Java8 String源码
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];//Java 9已经优化为byte数组了
/** Cache the hash code for the string */
private int hash; // Default to 0
...
}
显然String字符串内部是使用char[]数组来存储。
而这个char[]数组是用 private final来修饰的,private就体现着面向对象的封装特性,并且String没有提供供外部访问的方法,这就意味着这个属性无法被外部访问;final则意味着这个属性无法修改,无法重新指向其他对象。且String 类没有提供/暴露修改这个字符串的方法。
因此,String是不可变对象
不可变的优点
- 线程安全。同一个字符串实例可以被多个线程共享,因为字符串不可变,本身就是线程安全的。
- 支持hash映射。因为String的hash值经常会使用到,比如作为 Map 的键,不可变的特性也就使得hash值不会变,不需要重新计算。
- 字符串常量池优化。String对象创建之后,会缓存到字符串常量池中,下次需要创建同样的对象时,可以直接返回缓存的引用。
一定不可变吗
事实上,可以通过反射来改变String中的值
String str = "abcdef";
System.out.println("修改前的地址值:" + str + ",hash值"+ str.hashCode());
Class<? extends String> aClass = str.getClass();
Field value = aClass.getDeclaredField("value");
value.setAccessible(true);
value.set(str,"seven".getBytes());
System.out.println("修改后的地址值:" + str + ",hash值"+ str.hashCode());
显然修改后的还是同一个地址和hash值
修改前的地址值:abcdef,hash值-1424385949
修改后的地址值:seven,hash值-1424385949
查看源码可以看到,计算hashcode后hash值是由一个常量缓存下来的,所以通过反射修改后hashCode并不会变,除非进行重新计算。
注意:用反射修改String的值破坏了String的immutable特征,可能会带来各种问题,以上只是提供一个思路,不建议这么做。
不可变类都建议参考String类一样,写个变量缓存hashcode,从而防止高并发下的计算
public int hashCode() {
int h = hash;
if (h == 0 && !hashIsZero) {
h = isLatin1() ? StringLatin1.hashCode(value)
: StringUTF16.hashCode(value);
if (h == 0) {
hashIsZero = true;
} else {
hash = h;
}
}
return h;
}
关于作者
来自一线程序员Seven的探索与实践,持续学习迭代中~
本文已收录于我的个人博客:https://www.seven97.top
公众号:seven97,欢迎关注~
String真的不可变吗?的更多相关文章
- 在Java中String类为什么要设计成final?String真的不可变吗?其他基本类型的包装类也是不可变的吗?
最近突然被问到String为什么被设计为不可变,当时有点懵,这个问题一直像bug一样存在,竟然没有发现,没有思考到,在此总结一下. 1.String的不可变String类被final修饰,是不可继承和 ...
- Java 中的 String 真的是不可变吗?
我们都知道 Java 中的 String 类的设计是不可变的,来看下 String 类的源码. public final class String implements java.io.Seriali ...
- String 的不可变真的是因为 final 吗?
尽人事,听天命.博主东南大学硕士在读,热爱健身和篮球,乐于分享技术相关的所见所得,关注公众号 @ 飞天小牛肉,第一时间获取文章更新,成长的路上我们一起进步 本文已收录于 「CS-Wiki」Gitee ...
- Java中的String类真的不可变吗?java面试常见问题
其实在Java中,String类被final修饰,主要是为了保证字符串的不可变性,进而保证了它的安全性.那么final到底是怎么保证字符串安全性的呢?接下来就让我们一起来看看吧. 一. final ...
- Java基础知识强化101:Java 中的 String对象真的不可变吗 ?
1. 什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对 ...
- 为什么String被设计为不可变?是否真的不可变?
1 对象不可变定义 不可变对象是指对象的状态在被初始化以后,在整个对象的生命周期内,不可改变. 2 如何不可变 通常情况下,在java中通过以下步骤实现不可变 对于属性不提供设值方法 所有的属性定义为 ...
- String真的是不可变的吗?
你可能问一个人String是可变的吗?想必他们都会一口同生的说String是不可变的,因为String是final修饰的,而且它底层的是final修饰的char[]数组. 可以看到String源码: ...
- String为什么不可变
转载:http://www.importnew.com/7440.html https://www.cnblogs.com/leskang/p/6110631.html 什么是不可变对象? 众所周知, ...
- 从字节码和JVM的角度解析Java核心类String的不可变特性
1. 前言 最近看到几个有趣的关于Java核心类String的问题. String类是如何实现其不可变的特性的,设计成不可变的好处在哪里. 为什么不推荐使用+号的方式去形成新的字符串,推荐使用Stri ...
- 知识点:tuple 元素真的不可变吗
tuple 元素真的不可变吗 有一种有序列表叫元组:tuple. tuple和list非常类似,但是tuple一旦初始化就不能修改,比如同样是列出单位或同学的名字: >>> clas ...
随机推荐
- Apache Kylin(一)Kylin介绍
1. 传统大数据分析的问题 在基于Hadoop 生态的传统大数据分析中,主要使用的技术是MPP(Massively Parallel Processing)大规模并行处理和列式存储.MPP使用线性增加 ...
- 川普真会说中文?连嘴型都同步,VideoReTalking AI数字人下载介绍
你能想到这种画面吗?霉霉在节目中用普通话接受采访,特朗普在老家用中文脱口秀,蔡明老师操着一口流利的英文调侃潘长江老师.. 这听起来似乎很魔幻,可如今全部由VideoReTalking实现了 你只需要传 ...
- C#中?.、??、?:、及?等符号用途
1.可空类型修饰符(?) 众所周知,在C#中引用类型可以使用一个null引用来表示一个不存在的值,比如 string str = null 是正确的: 但是值类型却不能为空,比如 int k = ...
- 关于Precision,Recall,ROC曲线,KS,Lift等模型评价指标的介绍
1.Precision, Recall 准确率 \(Accuracy = \frac{TP+TN}{TP+TN+FP+FN}\) 精确率(或命中率) \(Precision = \frac{TP}{T ...
- 请解释一下 JavaScript 的同源策略?
概念:同源策略是客户端脚本(尤其是Netscape Navigator2.0,其目的是防止某个文档或脚本从多个不同源装载.这里的同源策略指的是: 协议,域名,端口 相同,同源策略是一种安全协议.指一 ...
- SpringBoot2.X定时任务schedule
什么是定时任务和常见定时任务区别? 某个时间定时处理某个任务 发邮件.短信等 消息提醒 统计报表系统 ... 常见定时任务 Java自带的java.util.Timer类配置比较麻烦,时间延后问题 Q ...
- Java开发工具和历史版本
eclipse 的历史版本: 版本代号 平台版本 主要版本发行日期 SR1发行日期 SR2发行日期 SR3发行日期 代号名称 N/A 3.0 2004年6月21日 [2] N/A N/A N/A N ...
- SCSS与CSS的区别
SCSS(Sassy CSS)是一种CSS预处理器,它扩展了CSS的功能,并为样式表的编写提供了额外的便利性.以下是两者之间的主要区别: 1. 语法扩展: CSS标准层叠样式表语言 ...
- suffix-icon属性隐藏el-select下拉框右边的下拉图标
<el-form-item label="入库类型" prop="mt_type"> <el-select v-model="for ...
- element-plus如何隐藏el-row
在 Element Plus 中,el-row 是用于布局的组件,如果你想要隐藏 el-row,你可以使用 CSS 的 display 属性将其设置为 none.以下是一个简单的示例: <tem ...