假设需要实现这样一个方法———该方法负责将一个Object[]数组的所有元素添加到一个Collection集合中
static void fromArrayToCollection(Object[] a, Collection<Object> b){
for (Object o:a){
b.add(o);
}
}
这个方法没有任何问题,关键在于方法中的b形参,它的数据类型是Collection
public static void main(String[] args) {
String[] strings = {"a", "b"};
List<String> stringList = new ArrayList<>();
//Collection<String>对象不能当成Collection<Object>使用,下面编译错误
fromArrayToCollection(strings,stringList);
}
这种情况下,使用类型通配符也不可以,因为Java不允许把对象放进一个未知类型的集合中。
为了解决这个问题,可以使用 Java 5 提供的泛型方法 :在声明方法时,定义一个或多个类型形参。
//类型形参声明放在方法修饰符与返回值之间
static <T> void fromArrayToCollection(T[] a, Collection<T> b){
for (T o:a){
b.add(o);
}
}
上面程序定义了一个泛型方法,该泛型方法中定义了一个T类型形参,这个T类型形参就可以在该方法内当做普通类来使用。
与类、接口中使用泛型参数不同的是:方法中的泛型参数不用显式传入值,系统依然可以知道类型形参的值,因为编译器根据实参推断类型形参的值。它通常推断出最直接的类型参数。
Object[] oa = new Object[10];
Collection<Object> co = new ArrayList<>();
//下面T代表Object类型
fromArrayToCollection(oa, co);
String[] sa = new String[10];
Collection<String> cs = new ArrayList<>();
//下面T代表String类型
fromArrayToCollection(sa, cs);
//下面T代表Object类型
fromArrayToCollection(sa,co);
Integer[] ia = new Integer[10];
Float[] fa = new Float[10];
Number[] na = new Number[10];
Collection<Number> cn = new ArrayList<>();
//下面T代表Number类型
fromArrayToCollection(ia, cn);
fromArrayToCollection(fa, cn);
fromArrayToCollection(na, cn);
为了让编译器能准确的推断出泛型方法中类型形参的类型,不要写出下面的这类谜语:
public class Demo3 {
static <T> void test(Collection<T> a, Collection<T> b){
for (T ele:a){
b.add(ele);
}
}
public static void main(String[] args) {
List<Object> lo = new ArrayList<>();
List<String> ls = new ArrayList<>();
//都是Collection<T>,这就要求两个集合实参中泛型类型相同
//编译错误,编译器无法准确的推断出泛型方法中 T 类型形参的类型
test(ls,lo);
}
}
可以改成如下:
public class Demo3 {
static <T> void test(Collection<? extends T> a, Collection<T> b){
for (T ele:a){
b.add(ele);
}
}
public static void main(String[] args) {
List<Object> lo = new ArrayList<>();
List<String> ls = new ArrayList<>();
test(ls,lo);
}
}
原文:https://www.cnblogs.com/woshi123/p/12512874.html