Java笔记之泛型方法

来源:互联网 发布:校园网络组建方案设计 编辑:程序博客网 时间:2024/05/17 16:13

1.定义泛型方法

所谓泛型方法,就是在声明方法时定义一个或多个类型形参。格式如下:

修饰符 <T,S> 返回值类型 方法名(形参列表){    //方法体...}

所有的类型形参放在方法修饰符和方法返回值类型之间。

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.泛型方法与通配符的区别

考虑如下两段代码:

public interface Collection<E>{    boolean containsAll(Collection<?> c);    boolean addAll(Collection<? extends E> c);    ...}public interface Collection<E>{    <T> boolean containsAll(Collection<T> c);    <T extends E> boolean addAll(Collection<T> c);    ...}

上面两个方法中类型形参T只使用了一次,类型形参T产生的唯一效果是可以在不同的调用点传入不同的实际类型。对于这种情况,应该使用通配符:通配符就是被设计用来支持灵活的子类化的。

泛型方法允许类型形参被用来表示方法的一个或多个参数之间的类型依赖关系,或者方法返回值与参数之间的类型依赖关系。如果没有这样的类型依赖关系,就不应该使用泛型方法。

如果某个方法中一个形参(a)的类型或返回值的类型依赖于另一个形参(b)的类型,则形参(b)的类型声明不应该使用通配符,因为如果形参(b)的类型无法确定,程序就无法定义依赖于它的形参(a)的类型。在这种情况下,只能考虑使用在方法签名中声明类型形参,也就是泛型方法。

如果有需要,也可以同时使用泛型方法和通配符。

两者还有一个显著的区别:类型通配符既可以在方法签名中定义形参的类型,也可以用于定义变量的类型;但泛型方法中的类型形参必须在对应方法中显式声明。

3.Java7的“菱形”语法与泛型构造器

如果程序显式指定了泛型构造器中声明的类型形参的实际类型,则不可以使用“菱形”语法,如下程序所示。

class MyClass<E>{    public <T> MyClass(T t)    {        System.out.println("t参数的值为:" + t);    }}public class GenericDiamondTest {    public static void main(String[] args)     {        //MyClass类声明中的E形参是String类型        //泛型构造器中声明的T形参是Integer类型        MyClass<String> mc1 = new MyClass<>(5);        //显式指定泛型构造器中声明的T形参是Integer类型        MyClass<String> mc2 = new <Integer> MyClass<String>(5);        //MyClass类声明中的E形参是String类型        //如果显式指定泛型构造器中声明的T形参是Integer类型        //此时就不能使用“菱形”语法,下面代码是错的        //MyClass<String> mc3 = new <Integer> MyClass<>(5);    }}

4.设定通配符下限

Java允许设定通配符的下限:<? super Type>,这个通配符表示它必须是Type本身,或是Type的父类。

public class MyUtils {    //下面dest集合元素的类型必须与src集合元素的类型相同,或是其父类    public static <T> T copy(Collection<? super T> dest , Collection<T> src)    {        T last = null;        for(T ele : src)        {            last = ele;            dest.add(ele);        }        return last;    }    public static void main(String[] args)     {        List<Number> ln = new ArrayList<>();        List<Integer> li = new ArrayList<>();        li.add(5);        Integer last = copy(ln,li);        System.out.println(ln);    }}
原创粉丝点击