string类为什么不可变,string类型不可变是什么意思
如何解决写爬虫IP受阻的问题?立即使用。
为何Java中String类是不可变的(详解)
公共最终类字符串
实现java.io.Serializable,ComparableString,CharSequence {
/**该值用于字符存储。*/
私有最终字符值[];}String类的值保存在value数组中,由private final修饰。
1.私有装饰表示外部类不能访问值,子类也不能访问。当然,String类不能有子类,因为类是用final修饰的。
2.最后的修饰表示value的引用不会改变,但是value只会在String的构造函数中初始化,没有其他方法可以修改value数组中的value,保证了value的引用和值不会改变。
所以我们说String类是不可变的。
很多方法,比如subString,并不是对原来的String类进行操作,而是生成一个新的String类。
公共字符串substring(int beginIndex) {
if (beginIndex 0) {
抛出新的StringIndexOutOfBoundsException(beginIndex);
}
int sub len=value . length-begin index;
if (subLen 0) {
抛出新的StringIndexOutOfBoundsException(subLen);
}
return (beginIndex==0)?this : new String(value,beginIndex,sub len);}为什么String被设置为不可变的?
字符串常量池
Java有8种基本数据类型
整数类型:字节,短整型,长整型.包装类型是字节,短,整数,长浮点类型:浮点,双精度。包类型为浮点型,双字符类型:char。包类型是字符布尔类型:布尔型。包类型为布尔型。
八种封装类型中,除了Float,Double没有实现常量池,其余的都实现了,当然都是通过元共享模式实现的。
字符串类的常量池是在JVM级别实现的。
为什么要有常量池?
恒池是为了避免频繁的创建和销毁对象会影响系统性能,它实现了对象的共享。
例如,字符串常量池,所有字符串在编译阶段都被放入一个常量池中。
节省内存空间:常量池中所有相同的字符串常量被合并,只占用一个空间。
节省运行时间:==比较字符串时比equals()快。对于两个引用变量,只用==来判断引用是否相等,使实际值相等。
字符串常量池放在哪?
jdk1.7之前没有讨论,从jdk1.7开始,字符串常量池就放在堆里了,然后本文的一切都是基于jdk1.8。
下面的代码经常被问到。
String str1= abc
String str2= abc
String str3=新字符串( ABC );
String str4=新字符串( ABC );
//true system . out . println(str 1==str 2);
//false system . out . println(str 1==str 3);
//false system . out . println(str 3==str 4);内存中的结构如下其中常量池中存的是引用
解释上面代码的输出。在Java中有两种创建字符串对象的方法。
String str1= abc
String str2= abc
//true system . out . println(str 1==str 2);当通过文字值创建一个字符串时,JVM将首先进入字符串池,找出对象“abc”是否存在。
如果不存在,在字符串池中创建对象 abc ,然后将池中对象 abc 的地址赋给str1,这样str1将指向池中的字符串对象 abc 。
如果存在,将不创建任何对象,直接返回池中对象‘ABC’的地址并赋给str2。结果为真,因为str1和str2指向同一个字符串池中的“abc”对象。
String str3=新字符串( ABC );
String str4=新字符串( ABC );
//false system . out . println(str 3==str 4);当使用new关键字创建新的字符串对象时,JVM首先在字符串池中搜索字符串对象“abc”的存在,
如果没有,首先在字符串池中创建一个 abc 字符串对象,然后在堆中创建一个 abc 字符串对象,然后将这个 abc 字符串对象在堆中的地址赋给str3。
如果是这样,不要在池中创建“abc”对象,而是直接在堆中创建“abc”字符串对象,然后将堆中此“abc”对象的地址分配给str4。这样,str4就指向了堆中创建的这个‘ABC’string对象;
因为str3和str4指向不同的string对象,所以结果为false。
缓存HashCode
创建String类时,hashcode缓存在hash成员变量中。因为String类是不可变的,所以hashcode不会改变。这样每次想用hashcode的时候,直接取就可以了,不用重新计算,提高了效率。
公共最终类字符串
实现java.io.Serializable,ComparableString,CharSequence {
/**缓存字符串的哈希代码*/
私有int哈希;//默认为0
}可以用作HashMap的key
由于String类的不可变属性,它经常被用作HashMap的键。如果String类是可变的,内容改变了,hashCode也会改变。当你根据这个键从HashMap中获取值时,你可能得不到值或者得到错误的值。
线程安全
不可变对象本质上是线程安全的,这可以避免在多线程环境中同步字符串。
感谢您的阅读,希望您能从中获益良多。
本文转自:https://blog.csdn.net/zzti_erlie/article/details/106872673
推荐教程:《java教程》以上是Java中String类为什么不可变的详细内容(详解)。更多请关注我们的其他相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。