如何声明数组,有几种方式,面试的时候经常被问道,每次都是临时记一下,也没有认真对待这个问题,现在复习一下。
数组的声明
最常用的声明方式
代码:
public static void main(String[] args) {
String[] strArr = new String[10];
strArr[10] = "145";
}
这是我最常用的声明方式,大多数使用数组时,都能确定数组中元素的个数。
这种写法,只是初始化了容量,但是具体的元素需要另外赋值。
但是一旦超过指定的容量,就会报错,上面代码执行就会报下面这个错误:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10
at test.TestArray.main(TestArray.java:14)
第二种声明方式
代码:
public static void main(String[] args) {
String[] strArr = new String[]{"0", "1"};
strArr[10] = "145";
}
这种写法不明显制定数组的容量,但是直接写出了数组拥有的元素,只有两个,也就是说数组容量就是2,如果执行上面的代码,也会报错:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10
at test.TestArray.main(TestArray.java:14)
第三种写法
代码:
public static void main(String[] args) {
String[] strArr = {"0", "1"};
strArr[10] = "145";
}
这种写法也是直接说明了数组的元素,同样无法超出容量范围。
总结:
以上三种写发,实际上是都必须指定数组的长度,超出长度就会报错。
扩容
集合和队列都有使用数组的实现,这些实现是允许一直添加的(直到溢出为止),这些实现都不是固定的长度的数组可以支持的,必须实现数组的扩容,现在就看一下数组如何扩容。
任何一个数组长度都是固定的,所谓扩容就是定义一个新的数组,把原来数组的元素复制到新的数组中。
因此,可以根据这种思想自己实现扩容方法,也可以使用Java提供的方法。
Java提供了两种方法:
– System.arraycopy()
– Arrays.copyOf()
先看第一种方法System.arraycopy()
源码:
* @param src the source array.
* @param srcPos starting position in the source array.
* @param dest the destination array.
* @param destPos starting position in the destination data.
* @param length the number of array elements to be copied.
* @exception IndexOutOfBoundsException if copying would cause
* access of data outside array bounds.
* @exception ArrayStoreException if an element in the <code>src</code>
* array could not be stored into the <code>dest</code> array
* because of a type mismatch.
* @exception NullPointerException if either <code>src</code> or
* <code>dest</code> is <code>null</code>.
*/
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
这是一个native方法,看不到实现,参数的注释非常的清楚,现在使用这个方法实现一个数组扩容。
测试代码:
public static void main(String[] args) {
String[] strArr = {"0", "1", "2"};
String[] newArr = new String[10];
System.arraycopy(strArr, 0, newArr, 3, 3);
strArr = newArr;
for (String s : strArr) {
System.out.println("元素:" + s);
}
}
输出结果:
元素:null
元素:null
元素:null
元素:0
元素:1
元素:2
元素:null
元素:null
元素:null
元素:null
可以看到现在strArr的长度是10,原来的元素复制到了3-5位上。
第二种实现方式Arrays.copyOf():
代码:
public static void main(String[] args) {
String[] strArr = {"0", "1", "2"};
//String[] newArr = new String[10];
//System.arraycopy(strArr, 0, newArr, 3, 3);
//strArr = newArr;
strArr = Arrays.copyOf(strArr, strArr.length + 7);
for (String s : strArr) {
System.out.println("元素:" + s);
}
}
输出:
元素:0
元素:1
元素:2
元素:null
元素:null
元素:null
元素:null
元素:null
元素:null
元素:null
这种扩容方式,无法指定复制开始的位置,也无法指定复制到的位置;
源码:
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
@SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
可以看到,这种扩容方式实际上也是使用System.arraycopy方法,只不过位置默认为0。
总结
1、数组的长度是固定的;
2、数组的扩容实际上是新建一个数组;