栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

String的不可变性

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

String的不可变性

String的不可变性
  • java中的字符串
    • java中string的源码
    • String的不可变性
    • String作为函数参数传递
    • 为什么java中要设计String的不可变性

java中的字符串

字符串,顾名思义就是一串字符,也就是一串连续的char.在c语言中就是用的char数组来表示的字符串.在java的一切皆对象世界中,将char数组进行了封装,用string类型来表达字符串.

java中string的源码
//java8源码
public final class String{
	private final char value[];
}

我们可以看到char数组被final关键字所修饰,并且是私有成员变量.
那么为什么java中要这么设计呢?这就要提到String的不可变性了.

String的不可变性
//Person是可变的
Person p = new Person(18);
p.setAge(20);

//String 是不可变的
String s = "JAVA";

如果我们可以修改对象的属性,那么我们就可以说,这个对象时可变的,反之,则是不可变的.
那么,String怎么就是不可变的了?

String s = "Java";
s="JavaScript";

System.out.println(s);//JavaScript


我们要注意,对象的不可变性,是指对象本身的属性或者说本身的数据不会改变,将变量重新赋值,我们是创建了一个新对象,让后将新对象的引用赋值给了变量(这里我们又要提到java只支持值传递,而对对象的传递,我们传递的是地址值),之前的对象是没有受到影响的.
Java中string的不可变性,不仅是源码之中char数组被private final所修饰,而且并没有提供任何修改字符数组的方法.一些字符串操作都是返回的新String对象,不会影响到原始数据.获取其底层字符数组时,都是复制一个新数组进行返回,原数组也不会受到影响.并且String类型还被final修饰了,代表其不可被继承,从而杜绝了子类覆盖父类行为的可能性.

String作为函数参数传递

String是特殊的引用类型,一旦初始化则是不可变的,可以当做是基本数据类型看待,因为基本数据类型也是不可变的。
String与基本数据类型作为参数传递时,传递的只是值的一个副本,在函数中对数据进行操作,不会改变原有的值,改变的只是副本值。
但是我们又知道java机制是只支持值传递,那么传递一般的对象,那不应该传递的是引用吗?
其实,java认为,即使传递的是引用,也把他看成地址值传递,所以就是值传递,实际上可以说是引用传递了,只不过传递的是地址值。
将对象作为参数传递,函数中对对象进行操作时,实际改变的就是对象本身,不存在副本或拷贝的情况。

为什么java中要设计String的不可变性

首先,只有String不可变了,堆中的字符串常量池才能发挥作用,用字面量创建字符串时,字符串常量池会返回已有对象的引用,如果字符串可变,那引用的值就可以随时改变,并能随时影响到其他的引用,从而数据会发生各种错误,这样常量池还谈何复用呢?
然后String不可变可以保证他的hash码也不会变,因此计算一次hash码后,就可以将其缓存,再用到时就无需计算了,性能更高.
也正是由于哈希码不会变,所以能搞放心的去使用与哈希码相关的对象,比如HashMap HashSet ,如果String的哈希码会变,那就会影响到这些对象的哈希计算,从而导致预期之外的结果,不如你之前明明存储了一个String的对象,到最后你找不到原对象了,


最后一个很重要的原因是,不可变对象都是线程安全的,因此你不用担心当前线程使用的对象会被其他的线程所改变,可以发现不可变对象有诸多的优点,所以java中有许多对象都设计成了不可变的,比如BigDecimal.

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/847124.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号