泛型方法
假设需要实现这样一个方法———该方法负责将一个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