当前位置: 首页 > 后端技术 > Java

为什么字符串是最终的

时间:2023-04-01 20:01:39 Java

源码状态阅读源码可以发现,String是finalized了,它的value变量也finalized了。这是两件事;首先,String类是finalized的,不能继承该类。避免有人试图通过继承和重写来破坏String的内部数据;其次,内部成员变量charvalue[]被final修饰,value的引用地址不可变;原因分析安全1.安全使用,String是最常用的对象,Immutable避免了直接改变堆中对象的内容。除非我们主动修改引用地址,否则我们将String传入任何方法,它都不会改变,以防止在其他函数中不小心被改变;2、线程安全,String并发使用时,无需考虑其线程安全问题;性能1、String缓冲池,采用享元模式,减少了String对象的生成,享元模式的缺点是对象内部状态不能改变;2、Hash算法,因为String初始化是不可变的,所以一个String的hashcode是固定不变的,只能计算一次,String最适合作为hashMap中的Key;个人思考为什么要final修改String类,先从字符串享元说起。假设String的定义产生了新的对象,那么在初始化多个“ABC”时,内存中就会有多个“ABC”字符串对象占用空间;这时候,考虑节省空间。你应该先创建一个内存空间来存放这个“ABC”,然后让所有需要使用这个字符串的对象直接指向这个地址;这时需要防止内存中“ABC”的值被其他人改变(即String的值),所以value变量被final修饰(如果不是final则内存空间中的值指针所指向的将被改变);如上,即使value被final修饰了,也有可能被子类通过重写方法Value来修饰,所以String类也是final修饰的,这样是不可变的,即一旦定义了String,它不会改变;publicfinalclassStringimplementsjava.io.Serializable,Comparable,CharSequence{/**该值用于字符存储。*/私有最终字符值[];/**缓存哈希码字符串*/privateinthash;//默认为0/**使用JDK1.0.2的serialVersionUID实现互操作性*/privatestaticfinallongserialVersionUID=-6849794470754667710L;/***类字符串在序列化流协议中是特殊情况。**String实例根据**对象序列化规范第6.2节“流元素”*/privatestaticfinalObjectStreamField[]serialPersistentFields=newObjectStreamField[0];/***初始化一个新创建的{@codeString}对象,使其代表一个空字符序列。请注意,不需要使用此构造函数,因为字符串是不可变的。*/publicString(){this.value="".value;}/***初始化一个新创建的{@codeString}对象,使其代表*与参数相同的字符序列;换句话说,*新创建的字符串是参数字符串的副本。除非需要{@codeoriginal}的*显式副本,否则不需要使用此构造函数,因为字符串是不可变的。**@paramoriginal*A{@codeString}*/publicString(Stringoriginal){this.value=original.value;this.hash=original.hash;}}