上一个例子是用泛型类的组合构建一个泛型类,那么如果有人问:如果想要从底层去构建一个泛型类,该怎么做?
答案就是这一节学习的内容,下面我们就用基本类型去构建一个泛型数据集合类。
除了使用Java泛型机制外,我们还需要使用java.lang.reflect.Array类来进行数组指定类型数组的创建。
1 学习java.lang.reflect.Array
Array类提供静态方法来动态创建和访问指定类型的Java数组。
1.1 Array.newInstance(Class<?> componentType, int length)
/**
*此方法可以根据传入的Class对象创建指定类型的数组
**/
public static Object newInstance(Class<?> componentType, int length)
throws NegativeArraySizeException {
return newArray(componentType, length);//调用底层jvm创建数组
}
其中返回的Object我们可以进行一次强转即可。
1.2 Array.getLength(Object array)
//jvm本地方法,用于计算数组长度
public static native int getLength(Object array)
throws IllegalArgumentException;
通过上面的两个API我们就可以创建自己的泛型数组集合类了。
这也从侧面反映了,泛型编程和反射机制搭配使用是最佳的使用方式。
1.3 Array.newInstance(Class<?> componentType, int… dimensions)
//创建多维数组
public static Object newInstance(Class<?> componentType, int... dimensions)
throws IllegalArgumentException, NegativeArraySizeException {
return multiNewArray(componentType, dimensions);}
2 正式构建自己的泛型集合
代码如下:
import java.lang.reflect.Array;
/**
* 泛型数组学习(结合反射实现泛型数组集合类)
* @param <T>
*/
public class GenericArray<T> {
//泛型数组
private T[] array;
//数组容量
private int size;
//当数组作为链表使用时,它是当前最后一个元素的索引
private int index;
@SuppressWarnings("unchecked")
public GenericArray(Class<T> type, int size) {
this.size = size;
//根据Class类型和size创建一个存放指定类型的指定大小的数组
array = (T[]) Array.newInstance(type, size);
index=0;
}
/**
* put方法用于向指定索引出插入一个元素
* @param index 索引位置
* @param item 插入的元素
*/
public void put(int index, T item) {
if (size > index) {
array[index] = item;
}else{
array = increaseArray(array);
array[index]=item;
}
}
/**
* 按顺序向数组中添加元素
* @param item 元素
*/
public void add(T item){
if(index>array.length-1){
array = increaseArray(array);
array[index]=item;
}else{
array[index]=item;
}
index++;
}
/**
* 获得数组中指定索引位置元素
* @param index 索引位置
* @return 元素
*/
public T get(int index) {
if (size > index) {
return array[index];
} else {
return null;
}
}
/**
* 数组扩容
* @param array 数组
* @return 扩容后的数组引用
*/
@SuppressWarnings("unchecked")
public T[] increaseArray(T[] array) {
// 获得代表数组的Class对象
Class<?> clazz = array.getClass();
// 如果输入是一个数组
if (clazz.isArray()) {
// 获得数组元素的类型
Class<?> componentType = clazz.getComponentType();
// 获得输入的数组的长度
int length = Array.getLength(array);
// 根据元素类型和length重新新建数组
T[] newArray = (T[])Array.newInstance(componentType, length + 5);
size=size+5;
// 复制原来数组中的所有数据到新数组中
System.arraycopy(array, 0, newArray, 0, length);
// 返回新建数组
return newArray;
}
// 如果输入的不是数组就返回空
return null;
}
public int getSize(){
return size;
}
}
下面进行测试:
public class GenericArrayTest {
public static void main(String[] args) {
System.out.println("创建String类型的数组并向其添加元素:四郎");
GenericArray<String> stringArray = new GenericArray<>(String.class, 3);
stringArray.put(0, "四郎");
stringArray.put(4,"麻子");
System.out.println(stringArray.getSize());
System.out.println(stringArray.get(4));
for (int i=0;i<stringArray.getSize();i++){
System.out.println(stringArray.get(i));
}
System.out.println("String类型的数组元素:" + stringArray.get(0));
System.out.println("创建Integer类型的数组并向其添加元素:123456789");
GenericArray<Integer> integerArray = new GenericArray<>(Integer.class, 2);
integerArray.add(1);
integerArray.add(2);
integerArray.add(3);
for (int i=0;i<integerArray.getSize();i++){
System.out.println(integerArray.get(i));
}
}
}
测试结果图如下: