一.自定义泛型方法
在javaAPI中,有很多的泛型方法,这些泛型方法给调用者提供了很大的方便,程序员在编写程序时,也体会到这些泛型的强大作用。现在,我们学习了泛型的基本使用技巧,那么,作为知识的拓展与提高,我们也应该模拟java开发者,开发属于自己定义的泛型方法,以便从底层了解泛型方法的定义。现在,我们先写一个泛型方法,来体验泛型方法的定义过程,如下代码所示:
package cn.itcast.generic;
public class GenericMethod {
/**自定义含有泛型的类或者方法,例如交换一个数组中的两个元素
* @param args
*/
public static void main(String[] args) {
//定义一个String类型的数组
String[] str = new String[]{"abc","123","xyz"};
//定义一个Integer类型的数组
Integer[] integer = new Integer[]{1,2,3,5};
//定义一个int类型的数组
int[] arr = new int[]{1,2,3};
//打印原数组
System.out.println("交换前:");
print(str);
print(integer);
//打印int类型的数组时会出现问题,说明泛型方法的实际参数只能是引用数据类型,
//不能是基本数据类型
//print(arr);
//交换数组中的两个元素
Swap(str,1,2);
Swap(integer,1,2);
//打印交换后的数组
System.out.println("交换后:");
print(str);
print(integer);
}
private static <T> void Swap(T[] t, int i, int j) {
T temp = t[i];
t[i] = t[j];
t[j] = temp;
}
private static <T> void print(T[] t) {
for(int i=0;i<t.length;i++){
System.out.print(t[i]+" ");
}
System.out.println();
}
}
我们先看一下程序的执行结果,编译运行后得到的结果如下所示:
交换前:
abc 123 xyz
1 2 3 5
交换后:
abc xyz 123
1 3 2 5
abc 123 xyz
1 2 3 5
交换后:
abc xyz 123
1 3 2 5
从结果我们可以分析出,该类定义了两个方法,分别用来打印数组中的元素和交换数组中的元素,可是在打印数组的元素中,数组元素类型是不确定的,这样根据我们以前学习的知识,接收的数据类型不一致,必须要用函数的重载,因此有几个类型的数组,就要定义几个方法,这样很麻烦,而我们定义一个泛型方法后,可以接收不同的数据类型,这样就节省了大量的代码,也为程序员节省了很多的时间和精力,代码也显得很简练。当然,他也有一定的局限性,比如我们上面代码的21行,我们调用print方法,方法的参数接收一个类型的数组,这时编译器会出错,也就是说泛型的参数必须接收一个引用型变量,而不能是基本类型的变量。这是我们在开发中必须要注意的地方。
二.自定义泛型类
学完了泛型方法之后,我们很自然的会想到我们能不能把一个类也加入泛型,变成泛型类呢,事实上是可以的,在java中,这种泛型类非常常见,比如在集合框架中,ArrayList<E>集合就是一个泛型类,由于ArrayList集合可以存储各种数据类型,因此他接受的数据类型是任意的,这样就是一个泛型类。下面我们来写一个属于自己的泛型类,如下代码所示:
package cn.itcast.generic;
import java.util.Set;
public class GenericDao<E> {
public void add(E e){
}
public E findByid(int id){
return null;
}
public void delete(int id){
}
public void delete(E obj){
}
public void update(E obj){
}
public Set<E> findByCondition(String where){
return null;
}
}
上面一个类是一个Dao类,在以后学习数据库时,会经常用到该类,它里面定义了数据增删改查方法,由于我们数据库可以操作各种数据类型,因此,我们往里面操作的对象是不确定的,我们需要泛型来定义这个类,它里面的方法需要用到泛型的数据类型就会和类中接收的数据类型一致,这样就方便了我们的操作。
三.泛型的总结和练习
这一段时间,一直在学习泛型,通过泛型的学习,我对java的理解更加深刻,下面我们用几个小小的练习来对泛型进行一个回顾吧。
1.编写一个程序,实现将一个Object类型的对象自动转化为其它数据类型,代码如下所示:
package GenericMethodExercise;
public class exercise1 {
/**自动将Object类型的对象转换为其它类型
* @param args
*/
public static void main(String[] args) {
Object obj = "abc";
String str = autoConvert(obj);
}
private static <T> T autoConvert(Object obj) {
return (T)obj;
}
}
上述方法实现了将一个Object类型的对象转成我们实际需要的数据类型,该方法接收的是一个Object数据类型的对象,返回的是我们需要的类型对象。
2.定义一个泛型方法,用于打印存储任意数据类型集合的元素,代码如下所示:
package GenericMethodExercise;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Exercise3 {
/**定义一个泛型方法,用于打印存储任意数据类型集合的元素
* @param args
*/
public static void main(String[] args) {
//建立一个存储String类型数据的集合
List<String> list = new ArrayList<String>();
//添加三条数据
list.add("java01");
list.add("java02");
list.add("java03");
//打印集合中的内容
print(list);
//建立一个存储Integer类型数据的集合
List<Integer> list1 = new ArrayList<Integer>();
//添加三条数据
list1.add(11);
list1.add(22);
list1.add(33);
//打印集合中的内容
print(list1);
}
private static <T> void print(List<T> list) {
Iterator<T> iterator = list.iterator();
while(iterator.hasNext()){
T value = iterator.next();
System.out.print(value+" ");
}
System.out.println();
}
}
上面代码实现了打印集合中的元素,但是该集合存储的元素类型时不确定的,因此提高了程序代码的重用性,当然要实现该功能,用泛型通配符也可以,具体的实现方法可以参照我上一篇的泛型通配符示例,这里不再演示。