//声明:部分内容引自《Java编程思想(第四版)》机械工业出版社
【数组是第一级对象】
– 对象数组和基本类型数组在使用上几乎是相同的,唯一的区别是对象数组保存的是引用,基本类型数组直接保存基本类型的值。
– 基本类型数组的值在不进行显式初始化的情况下,会被自动初始化,对象数组会被初始化为 null。
【返回一个数组】
– 一个方法可以返回一个数组,当使用完毕后,垃圾回收器会清理掉它。
【数组与泛型】
– 通常,数组与泛型不能很好的结合。你不能实例化具有参数化类型的数组:Peel<Banana>[] peels = new Peel<Banana>[10]; // Illegal
擦除会移除参数类型信息,而数组必须知道它们所持有的确切类型,以强制保证类型安全。但是,可以参数化数组本身的类型。
例:
package arrays;//: arrays/ParameterizedArrayType.java
class ClassParameter<T> {
public T[] f(T[] arg) { return arg; }
}
class MethodParameter {
public static <T> T[] f(T[] arg) { return arg; }
}
public class ParameterizedArrayType {
public static void main(String[] args) {
Integer[] ints = { 1, 2, 3, 4, 5 };
Double[] doubles = { 1.1, 2.2, 3.3, 4.4, 5.5 };
Integer[] ints2 =
new ClassParameter<Integer>().f(ints);
Double[] doubles2 =
new ClassParameter<Double>().f(doubles);
ints2 = MethodParameter.f(ints);
doubles2 = MethodParameter.f(doubles);
}
} ///:~
使用参数化方法而不使用参数化类的方便之处在于:你不必为需要应用的每种不同的类型都使用一个参数去实例化这个类,并且你可以将其定义为静态的。
– 可以这样创建数组引用:List<String>[] ls;
– 可以创建非泛型的数组,然后将其转型,例:
package arrays;//: arrays/ArrayOfGenerics.java
// It is possible to create arrays of generics.
import java.util.*;
public class ArrayOfGenerics {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
List<String>[] ls;
List[] la = new List[10];
ls = (List<String>[])la; // "Unchecked" warning
ls[0] = new ArrayList<String>();
// Compile-time checking produces an error:
//! ls[1] = new ArrayList<Integer>();
// The problem: List<String> is a subtype of Object
Object[] objects = ls; // So assignment is OK
// Compiles and runs without complaint:
objects[1] = new ArrayList<Integer>();
// However, if your needs are straightforward it is
// possible to create an array of generics, albeit
// with an "unchecked" warning:
List<BerylliumSphere>[] spheres =
(List<BerylliumSphere>[])new List[10];
for(int i = 0; i < spheres.length; i++)
spheres[i] = new ArrayList<BerylliumSphere>();
}
} ///:~
– 如果创建一个 String[],Java 在编译期和运行时都会要求我只能将 String 对象置于该数组中。但是,如果创建的是 Object[],那么就可以将除基本类型之外的任何对象置于该数组中。
【创建测试数据】
– Arrays.fill()。只能用同一个值填充各个位置,而针对对象而言,就是复制同一个引用进行填充。
例:
package arrays;//: arrays/FillingArrays.java
// Using Arrays.fill()
import java.util.*;
import static net.mindview.util.Print.*;
public class FillingArrays {
public static void main(String[] args) {
int size = 6;
boolean[] a1 = new boolean[size];
byte[] a2 = new byte[size];
char[] a3 = new char[size];
short[] a4 = new short[size];
int[] a5 = new int[size];
long[] a6 = new long[size];
float[] a7 = new float[size];
double[] a8 = new double[size];
String[] a9 = new String[size];
Arrays.fill(a1, true);
print("a1 = " + Arrays.toString(a1));
Arrays.fill(a2, (byte)11);
print("a2 = " + Arrays.toString(a2));
Arrays.fill(a3, 'x');
print("a3 = " + Arrays.toString(a3));
Arrays.fill(a4, (short)17);
print("a4 = " + Arrays.toString(a4));
Arrays.fill(a5, 19);
print("a5 = " + Arrays.toString(a5));
Arrays.fill(a6, 23);
print("a6 = " + Arrays.toString(a6));
Arrays.fill(a7, 29);
print("a7 = " + Arrays.toString(a7));
Arrays.fill(a8, 47);
print("a8 = " + Arrays.toString(a8));
Arrays.fill(a9, "Hello");
print("a9 = " + Arrays.toString(a9));
// Manipulating ranges:
Arrays.fill(a9, 3, 5, "World");
print("a9 = " + Arrays.toString(a9));
}
} /* Output:
a1 = [true, true, true, true, true, true]
a2 = [11, 11, 11, 11, 11, 11]
a3 = [x, x, x, x, x, x]
a4 = [17, 17, 17, 17, 17, 17]
a5 = [19, 19, 19, 19, 19, 19]
a6 = [23, 23, 23, 23, 23, 23]
a7 = [29.0, 29.0, 29.0, 29.0, 29.0, 29.0]
a8 = [47.0, 47.0, 47.0, 47.0, 47.0, 47.0]
a9 = [Hello, Hello, Hello, Hello, Hello, Hello]
a9 = [Hello, Hello, Hello, World, World, Hello]
*///:~
– 数据生成器。
– 从 Generator 中创建数组。
【Arrays 实用功能】
– 复制数组。System.arraycopy()
需要的参数有:源数组。表示从源数组中的什么位置开始复制的偏移量,表示从目标数组的什么位置开始复制的偏移量,以及需要复制的元素个数。对数组的任何越界操作都会导致异常。
如果复制对象数组,那么只能复制了对象的引用,而不是对象本身的拷贝,这被称作浅复制。
System.arraycopy()
不会执行自动包装和自动拆包,两个数组必须具有相同的确切类型。
– 数组的比较。
– 数组元素的比较。
– 数组排序。
– 在已排序的数组中查找。Arrays.binarySearch()
如果对未排序数组使用,将产生不可预料的后果。
【总结】 ##
– 优选容器而不是数组。