泛型是Java SE 5.0版的重要特性,使用泛型编程可以提高代码的重用性。泛型在Java中有比较重要的地位,在面向对象编程以及其他各种设计模式中有非常广泛的应用。
什么是泛型:泛型即是“参数化类型”,也就是将类型由原来具体的类型参数化,类似于方法中的变量参数,此时类型也定义为参数形式。
使用通配符增加泛型
利用泛型类型参数<T>可以将类、方法或接口限制为T类型,但这种方式有个明显缺点就是不够灵活,一旦指定了该类型就不能再修改。这时候可以使用通配符会让代码更加灵活。
例 下面的getMiddleNumber()方法用于获取指定列表的中间值,该方法参数中要求参数的类型是任何Number类型的子集。
public static Object getMiddleNumber(List<? extends Number> list) {
return list.get(list.size() / 2); //返回中间值
}
public static void main(String[] args) {
List<Integer> arrayInt = new ArrayList<Integer>();//整型列表
arrayInt.add(1);
arrayInt.add(2);
arrayInt.add(3);
arrayInt.add(4);
arrayInt.add(5);
System.out.print("整型类型");
System.out.println(Arrays.toString(arrayInt.toArray()));
System.out.println("整型列表的中间数:" + getMiddleNumber(arrayInt));
List<Double> arrayDoubles = new ArrayList<Double>();
arrayDoubles.add(1.1);
arrayDoubles.add(2.2);
arrayDoubles.add(3.3);
System.out.print("浮点类型:");
System.out.println(Arrays.toString(arrayDoubles.toArray()));
System.out.println("浮点列表的中间数:" + getMiddleNumber(arrayDoubles));
}
泛型中,使用“?”作为通配符,通配符的使用与普通参数类似,通配符也可以利用extends关键字来设置取值上值或下值。
运行结果
泛型化的折半查找法
在数据结构中,查找有很多种类型,比如顺序查找、折半查找等。如何使用泛型实现折半查找法。
下面方法使用search()方法在给定的数据中查找指定key的索引。
public static <T extends Comparable<? super T>> int search(T[] array, T key) {
int min = 0; //该变量保存数组的最小索引
int middle = 0; //该变量保存数组的中间索引
int max = array.length; //该变量保存数组的最大索引
System.out.println("中间值:");
while (min <= max) {
middle = (min + max) / 2; //获取中间索引
System.out.print(middle+" ");
//key值大于中间元素,则比较右边
if (key.compareTo(array[middle]) > 0) {
min = middle + 1;
}
//key值小于中间元素,则比较左边
else if (key.compareTo(array[middle]) < 0) {
max = middle - 1;
} else {
System.out.println();
return middle; //返回对应元素的索引
}}
return -1; //没有找到返回-1
}
public static void main(String[] args) {
Integer[] arrayInt = {1,2,3,4,5,6,7,8,9,0};//定义数组
System.out.println(Arrays.toString(arrayInt));
System.out.println("元素8所对于的索引序号:"+search(arrayInt, 8));
}
注:折半查找法要求的数据集合中的元素是必须可比较,并各元素按升序或降序排序。取集合的中间元素作为比较对象,则如果指定的值与比较对象相等,查找成功,返回中间元素的序号,但如果指定的值大于比较对象,则会在中间元素的右半段进行查找,若小于比较对象则在中间元素的左半段进行查找。该算法的平均时间复杂度是log2n
自定义泛型化数组类
在Java虚拟机中没有泛型类型的对象,所有有关泛型的信息都给擦除了,这样导致不能直接创建泛型数组,不过可以使用反射机制来创建一个泛型化的数组。
自定义泛型类
public class MyGeneric<T> {
private T[] array; //类型为T的数组
private int size; //数组长度
public MyGeneric(Class<T> type, int size) {
this.size = size;
//利用反射根据指定的类型和长度创建泛型数组
array = (T[]) Array.newInstance(type, size);
}
public void put(int index, T item) {//数组添加方法
if (size > index) {
array[index] = item;
}
}
//获取数组中元素
public T get(int index) {
if (size > index) {
return array[index];
} else {
return null;
}
}
}
@Test
public void test() {
System.out.println("String数组");
MyGeneric<String> stringArray = new MyGeneric<String>(String.class, 10);
stringArray.put(0, "测试字符串");
System.out.println("String数组" + stringArray.get(0));
System.out.println("Integer数组");
MyGeneric<Integer> integerArray = new MyGeneric<Integer>(Integer.class, 10);
integerArray.put(0, 147258369);
System.out.println("Integer数组" + integerArray.get(0));
}
运行上面的test()方法结果如下