在上周的文章中,咱们讲了字符串拼接的多种形式,在StringBuilder和StrngBuffer的形象父类AbstractStringBuilder的append办法中,咱们应用了ensureCapacityInternal函数,明天我就带大家看看理解下这个函数
上期的链接:java-字符串拼接的多种形式(1)
//调用函数,这里的调用程序就是自上而下的private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code if (minimumCapacity - value.length > 0) { //从0开始复制数组自身,并采纳新的长度 value = Arrays.copyOf(value, newCapacity(minimumCapacity)); }}
//返回新的容量private int newCapacity(int minCapacity) { // overflow-conscious code //在这里,负数的左移1位指2进制的数左移一位,再用0补充;如原来是0011(3),左移为0110(6) //他们的十进制之间的关系是2倍的关系,即2的一次方 int newCapacity = (value.length << 1) + 2; //当新的容量依然小于理论须要的长度的时候 if (newCapacity - minCapacity < 0) { newCapacity = minCapacity; } //举例,当value.length为2136372536的时候,newCapacity的符号位因为溢出而扭转, //超过int的最大值,因而符号位变成了"1",也就是由负数变成正数,这时便满足<=0条件 return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0) ? hugeCapacity(minCapacity) : newCapacity;}
//用于微小的新容量的获取//集体了解:数据和对象的长度并不是真正的由MAX_ARRAY_SIZE来决定,而是由你实际上存储的jvm虚拟机的存储来决定的//状况1:举个例子,你的int数组的长度是21亿,他须要21亿乘4字节,估算就是8.4G,这通常会超过咱们设置的jvm的堆空间大小//这就是为什么咱们超堆内存创立数组的时候,他会报出OutOfMemoryError: Java heap space//状况2:而当咱们超jvm标准创立数据的时候,如Integer.MAX_VALUE-1和Integer.MAX_VALUE;他会报出OutOfMemoryError: Requested array size exceeds VM limit;或者不同的jvm有不同的底线吧//状况3:而当咱们超过Integer.MAX_VALUE,他传递给StringBuilder的值超过了int类型的最大值,底层会变成了正数,他会报出NegativeArraySizeExceptionprivate int hugeCapacity(int minCapacity) { if (Integer.MAX_VALUE - minCapacity < 0) { // overflow throw new OutOfMemoryError(); } //返回最小容量和最大的数组容量中更大的那个 return (minCapacity > MAX_ARRAY_SIZE) ? minCapacity : MAX_ARRAY_SIZE; }
总结
1. 集体纳闷:在学习源码的过程中,我在思考为什么MAX_ARRAY_SIZE=Integer.MAX_VALUE - 8,查问说是要存储一些要害的信息?为什么arraylist中的hugeCapacity是能够超过MAX_ARRAY_SIZE的值的,凭什么,你能超出,我却不能?
2. 闲聊:写代码的过程中查问了很多材料,有时候在想为什么要写博客,明明很多人都曾经写过了,你再写又有什么意义呢。往大一点说,我想看看他人帅气的代码,理解哪些平凡的程序员所做过的事;往小了说,我以前就心愿当我有一天来到这个世界的时候,有本书它记录着我从小到大的生存经验和感悟,写博客也是一种记录吧,兴许有一天当我看见这些博客,也会回忆起那些早晨打字的时光,或者那也是一种年老的回顾呢,哈哈哈!