一 泛型方法的介绍
如果定义类、接口是没有使用类型形参,但定义方法时想自己定义类型形参,这也是可以的,JDK1.5还提供了泛型方法的支持。
泛型方法的语法格式为:
修饰符 <T , S> 返回值类型 方法名(形参列表)
{
//方法体...
}
泛型方法的方法签名比普通方法的方法签名多了类型形参声明,类型形参声明以尖括号括起来,多个类型形参之间以逗号(,)隔开,所有类型形参声明放在方法修饰符和方法返回值类型之间。
二 泛型方法的正确使用
1 代码示例
import java.util.*;
public class GenericMethodTest
{
// 声明一个泛型方法,该泛型方法中带一个T类型形参,
static <T> void fromArrayToCollection(T[] a, Collection<T> c)
{
for (T o : a)
{
c.add(o);
}
}
public static void main(String[] args)
{
Object[] oa = new Object[100];
Collection<Object> co = new ArrayList<>();
// 下面代码中T代表Object类型
fromArrayToCollection(oa, co);
String[] sa = new String[100];
Collection<String> cs = new ArrayList<>();
// 下面代码中T代表String类型
fromArrayToCollection(sa, cs);
// 下面代码中T代表Object类型
fromArrayToCollection(sa, co);
Integer[] ia = new Integer[100];
Float[] fa = new Float[100];
Number[] na = new Number[100];
Collection<Number> cn = new ArrayList<>();
// 下面代码中T代表Number类型
fromArrayToCollection(ia, cn);
// 下面代码中T代表Number类型
fromArrayToCollection(fa, cn);
// 下面代码中T代表Number类型
fromArrayToCollection(na, cn);
// 下面代码中T代表Object类型
fromArrayToCollection(na, co);
// 下面代码中T代表String类型,但na是一个Number数组,
// 因为Number既不是String类型,
// 也不是它的子类,所以出现编译错误
// fromArrayToCollection(na, cs);
}
}
2 代码说明
与类、接口中使用泛型参数不同的是,方法中的泛型参数无需显式传入实际类型参数,因为编译器根据实参推断类型形参的值。它通常推断出最直接的类型参数。例如:调用如下代码。
fromArrayToCollection(sa, cs);
上面代码中cs是一个Collection<String>类型,与方法定义时的fromArrayToCollection(T[] a, Collection<T> c)进行比较,只比较泛型参数,不能发现该T类型形参代表的实际类型是String类型。
三 泛型方法的错误使用
1 代码示例
import java.util.*;
public class ErrorTest
{
// 声明一个泛型方法,该泛型方法中带一个T类型形参
static <T> void test(Collection<T> from, Collection<T> to)
{
for (T ele : from)
{
to.add(ele);
}
}
public static void main(String[] args)
{
List<Object> as = new ArrayList<>();
List<String> ao = new ArrayList<>();
// 下面代码将产生编译错误
test(as , ao);
}
}
2 运行结果
E:\test\Java\Java8\fanxing\src>javac ErrorTest.java
ErrorTest.java:20: 错误: 无法将类 ErrorTest中的方法 test应用到给定类型;
test(as , ao);
^
需要: Collection<T>,Collection<T>
找到: List<Object>,List<String>
原因: 推断类型不符合等式约束条件
推断: String
等式约束条件: String,Object
其中, T是类型变量:
T扩展已在方法 <T>test(Collection<T>,Collection<T>)中声明的Object
1 个错误
3 代码说明
上面程序中调用了test方法传入了两个实际参数,其中as的数据类型是List<String>,而ao的数据类型是List<Object>,与泛型方法签名进行对比test(Collection<T> a,Collection<T> c),编译器无法正确识别T所代表实际类型。
四 改进上面这个例子
1 代码示例
import java.util.*;
public class RightTest
{
// 声明一个泛型方法,该泛型方法中带一个T形参
static <T> void test(Collection<? extends T> from , Collection<T> to)
{
for (T ele : from)
{
to.add(ele);
}
}
public static void main(String[] args)
{
List<Object> ao = new ArrayList<>();
List<String> as = new ArrayList<>();
// 下面代码完全正常
test(as , ao);
}
}
2 代码说明
该代码可以编译通过,它改变了test签名,将该方法的前一个形参类型改为Collection<? extends T>,这种采用类型通配符的表示方式,只要test方法的前一个Collection集合里的元素类型是后一个Collection集合里的元素类型的子类即可。