关于数组的赋值问题
java的基础语法已经学习完了,上了某个自学网站回顾了一下,有个自制StringBuffer和String比较性能的作业,就尝试了一下,途中踩了一点坑,写个博客记录一下。
这里我参考了一下StringBuffer的源码编写一下insert方法,发现,当程序执行到到14行的时候,JVM虚拟机抛出了一个java.lang.ArrayIndexOutOfBoundsException
给我,当时很困惑,debug半天没发现问题
1 public void insert(int pos, String b) {
2 /*判断边界条件*/
3 if (pos < 0) return;
4 if (pos > length) return;
5 //如果现在数组的长度加上新增字符串的长度大于原先设定的容量,扩容
6 while (length + b.length() > capacity) {
7 capacity = (int) (length + b.length() * 1.5f);
8 char[] newValue = new char[capacity];
9 System.arraycopy(value, 0, newValue, 0, value.length);
10 value = newValue;
11 }
12 char[] cs = b.toCharArray();
13 //将要插入的位置后面的字符向后挪
14 System.arraycopy(value, pos, value, pos + cs.length, length - pos);
15 //把要插入的数据插入到指定位置
16 System.arraycopy(cs, 0, value, pos, cs.length);
17 length += length + cs.length;
后来当我每个位置都判断了一下我设定的容量大小和数组长度之后,终于发现问题,在15行,我的字符数组长度和我设定的初始容量不相符,所以导致了越界,我又翻回前面查找错误。
1 public void insert(int pos, String b) {
2 System.out.println("capacity.."+capacity);//16
3 /*判断边界条件*/
4 if (pos < 0) return;
5 if (pos > length) return;
6 //如果现在数组的长度加上新增字符串的长度大于原先设定的容量,扩容
7 while (length + b.length() > capacity) {
8 capacity = (int) (length + b.length() * 1.5f);
9 char[] newValue = new char[capacity];
10 System.arraycopy(value, 0, newValue, 0, value.length);
11 value = newValue;
12 }
13 char[] cs = b.toCharArray();
14 //把已存在的数据往后推
15 System.out.println("value.length..." + value.length);//4
16 System.out.println("pos+cs.length..." + (pos + cs.length));//4
17 System.out.println("pos+cs.length是否大于value.length..." + ((pos + cs.length) > value.length));//false
17 System.arraycopy(value, pos, value, pos + cs.length, length - pos);//程序运行到这里会抛出异常
19 //把要插入的数据插入到指定位置
20 System.arraycopy(cs, 0, value, pos, cs.length);
21 length += length + cs.length;
22 }
这里是我设定的初始容量,和实例化类的同时初始化一个数组
1 int capacity = 16;
2 int length = 0;
3 char[] value;
4
5 public MyStringBuffer() {
6 //建立新的数组
7 value = new char[capacity];
8 length = value.length;//16
9 }
下面是在初始化MyStringBuffer之后,在构造方法里面添加要存入的字符串,this()是调用了上面的构造方法。
通过检查各部分的变量值发现,在第7行这个地方,value.length的长度变成了4,数组的初始容积仍然为16。而上面初始化的时候,value.length的长度是16。
1 public MyStringBuffer(String str) {
2 this();
3 //非空判断
4 if (null == str) return;
5 value = str.toCharArray();
6 length = value.length;
7 System.out.println("赋值后的length..." + length);//4
8 System.out.println("赋值后的容量... " + capacity);//16
9 //边界条件判断
10 if (capacity < value.length) {
11 capacity = value.length * 2;
12 value = new char[capacity];
13 }
14 if (capacity >= str.length()) {
15 System.arraycopy(str.toCharArray(), 0, value, 0, str.length());//如果大于存入的长度,就赋值数组
16 }
17 }
这时候我才发现,所有的坑,都集中在第5行上面。
1 public MyStringBuffer(String str) {
2 this();
3 //非空判断
4 if (null == str) return;
5 value = str.toCharArray();
6 length = value.length;
这里的value虽然在之前初始化了,但是,由于str.toCharArray()返回的也是一个字符数组,相当于value重新指向了一个长度为4的字符数组,导致了后面在做字符插入的时候越界了。