扫码关注公众号
关于String,StringBuilder以及StringBuffer,描述错误的是()
正确答案是CA,java中的字符串存储在字符串常量区,不会改变,发生改变是会新创建一个对象B,StringBuffer是线程安全的Strin
String, StringBuffer和StringBuilder区别
String和StringBuffer主要区别是性能:String是不可变对象,每次对String类型进行操作都等同于产生了一个新的Stri
java的基本类型有哪几个?String是不是java的基本类型?
一共有八种基本类型。1.六种数字类型:整型(四个)和浮点型(两个)字节型:byte---------8位短整型:short--------16位整型:int---------------32位长整型:long----------64位单精度:float:-------32位双精度:double-------64位2.一种字符型:字符型:char----------8位3.一种布尔型布尔型:Boolean----8位String不是基本数据类型,它本身是个对象,是final修饰的java类,是引用类型
简单说明String类为什么是final的
声明为final类的目的主要目的就是保证String是不可变(immutable)。不可变就是第二次给一个String变量赋值的时候,不是在原内存地址上修改数据,而是重新指向一个新对象,新地址。下面看String类源码如何保证是不可变的:publicfinalclassStringimplementsjava.io.Serializable,Comparable<String>,CharSequence{/**Thevalueisusedforcharacterstorage.*/privatefinalcharvalue[];...String类的主力成员字段value是个char[]数组,而且是用final修饰的。编译器不允许把value指向另一个地址。但可以直接对数组元素修改。为了保证这个数组元素不能修改,做了如下措施:(1)所有String的方法里很小心的没有去动数组里的元素,没有暴露内部成员字段。(2)避免被其他人继承后破坏,整个String设成final禁止继承。如果有一个String的引用,它引用的一定是一个String对象,而不可能是其他类的对象。为什么要不String设计为不可变1.从内存角度来看字符串常量池的要求:创建字符串时,如果该字符串已经存在于池中,则将返回现有字符串的引用,而不是创建新对象。字符串池的实现可以在运行时节约很多heap空间,多个String变量引用指向同一个内地地址。如果字符串是可变的,用一个引用更改字符串将导致其他引用的值错误。这是很危险的。2.缓存Hashcode字符串的Hashcode在java中经常配合基于散列的集合一起正常运行,这样的散列集合包括HashSet、HashMap以及HashTable。不可变的特性保证了hashcode永远是相同的。不用每次使用hashcode就需要计算hashcode。这样更有效率。因为当向集合中插入对象时,是通过hashcode判别在集合中是否已经存在该对象了(不是通过equals方法逐个比较,效率低)。3.方便其它类使用其他类的设计基于string不可变,如set存储string,改变该string后set包含了重复值。4.安全性String被广泛用作许多java类的参数,例如网络连接、打开文件等。如果对string的某一处改变一不小心就影响了该变量所有引用的表现,则连接或文件将被更改,这可能导致严重的安全威胁。不可变对象不能被写,所以不可变对象自然是线程安全的,因为不可变对象不能更改,它们可以在多个线程之间自由共享。总结由于效率和安全性的原因,字符串被设计为不可变
StringBuffer是怎么扩容的?
首先我们需要知道StringBuffer和StringBuilder类都继承了抽象类AbstractStringBuilder类;源码都调用父类来进行初始化:StringBuffer(Strings)的初始化:扩容算法:使用append()方法在字符串后面追加值的时候,如果长度超过了该字符串存储空间大小了就需要进行扩容:构建新的并且存储空间更大的字符串,将旧的复制过去;在进行字符串append添加的时候,会先计算添加后字符串大小,传入一个方法:ensureCapacityInternal这个方法进行是否扩容的判断,需要扩容就调用expandCapacity方法进行扩容:尝试将新容量扩为原大小的2倍+2(加2是因为拼接字符串通常末尾都会有个多余的字符),如果扩充后的容量还是不够,则直接扩充到需要的容量大小。例子: