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 ...
随机推荐
- 在centos开启防火墙没启动22/tcp or 22/udp的情况下是如何ssh连上的
偶尔间查询防火墙的22/tcp or 22/udp ,看到是no的状态,而且此时也是ssh登陆的,然后就反复尝试,关闭22端口,开启,重载,重启.甚至连上另个服务器发现还是一样的情况.在群里问大佬们终 ...
- 震撼登场,全国产RK3588J工业核心板,让您的产品更具特色!八核2.4GHz!
RK3588J全国产工业核心板10月正式出售如需预定,请与创龙科技联系. 更多详情,请登录创龙科技天猫旗舰店. 瑞芯微RK3568J.RK3588J技术交流QQ群:567208221,欢迎加入!
- 移动web布局方法
继续更新移动端的一个布局,这也是经典中的经典,当初只知道个rem和vwvh适配,其实这里面还有很多的门道不只是一个适配这么简单 一.前置 1.背景缩放 我们都知道做移动端,给的图都是二倍图,你拿来用直 ...
- python3 模型日记
说明 作为一种 python 框架模型的记录吧,用于个人总结,不定时更新. 正文 1. 主进程退出后,子进程也跟着退出 之前遇到过一种情况,用 flet 写了一个页面,然后又同时开了一个 tcp se ...
- VulnHub_DC-3渗透流程
VulnHub_DC-3 DC-3 是另一个特意建造的易受攻击的实验室,旨在获得渗透测试领域的经验. 与之前的 DC 版本一样,这个版本是为初学者设计的,尽管这一次只有一个flag.一个入口点并且根本 ...
- Spring的xml和注解对比
常用注解 bean定义 XML方式:<bean></bean> 注解方式:@Component 通用组件 @Controller(web层) @Service(service层 ...
- win10打不出中文的修复方法!
说明 在Win10系统中,默认自带了中文输入法,使用起来非常的方便,但有时win10系统中自带的输入法会打不出中文的情况,该怎么办呢?遇到这样的问题,我们可以参考下本文中的方法来修复. 步骤: cmd ...
- Git 清除缓存账密
[已解决] git push 报错:git: 'credential-manager' is not a git command. See 'git --help'. 解决方案1)运行 git con ...
- vue 理解yarn start 和yarn dev的区别
yarn dev,当文件变动后,会自动重启. yanr start不会自动重启 nodemon会监听文件变动,跟yarn dev和yarn start无关.
- Java 监听POST请求
要监听POST请求,我们可以使用Java中的HttpServlet类.以下是一个使用Servlet API监听POST请求的完整示例.这个示例使用了Servlet 3.1规范,不需要在web.xml中 ...