A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 黄治文 黑马帝   /  2011-10-9 02:16  /  3303 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

  1. public static void printCollection(Collection<?> col) {
  2.                 System.out.println(col.size());
  3.         }
复制代码
  1. public static void printCollection(Collection col) {
  2.                 System.out.println(col.size());
  3.         }
复制代码
有什么实际的区别吗?在实际开发中泛型通配符有什么用处?在什么情况下能体现出其强大的功能?

4 个回复

倒序浏览
使用?通配符可以引用各种参数类型,?通配符定义的变量主要用于引用,可以调用与参数无关的方法,不能定义与参数有关的方法
回复 使用道具 举报
在大多数情况下泛型方法可以用来代替通配符,例如对于集合框架中的Collection接口的两个方法定义:

public interface Collection<E>{

boolean containsAll(Collection<?> c);

boolean addAll(Collection<?Exends E> c);

}

在上面的集合中两个方法的形式参数都是采用了通配符的形式,那么此时也可以使用泛型方法来代替类型通配符的使用:

public interface Collection<E>{

boolean<T>   containsAll(Collection<T> c);

boolean<T extends E>   addAll(Collection<T> c);

}

上面的方法使用了<T extends E> 泛型形式,其作用是定义类型形参时指定其上限.

特别注意的是:在这两个方法中,类型形参T只使用了一次,类型形参T的唯一效果是可以在不同的调用点传入不同的实际类型.对于这种情况,应该使用通配符.

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

如果需要,也可以同时使用泛型方法和通配符.例如Collections 类中的copy()方法:

class Collections{

public static<T>void copy(List<T>d,LIst<?Extends T>s){

//代码实现

}

}

在 copy()方法中,两个参数之间存在明显的依赖关系,即从源程序中赋值出来的元素,必须要复制到目标程序中,所以集合元素的类型只能是目标集合元素的类型本身或是其子类的类型.但是在JDK中表示源程序的S形参使用的是通配符,而不是泛型方法,是因为该方法无需向源程序集合中添加元素,也无需改变源程序集合里的元素,所以可以使用类型通配符,无需使用泛型方法.

对于上面的代码,也可以采用泛型方法,而不使用通配符,修改后代码如下:

class Collections{

public static<T>void copy(List<T>d,LIst<S>s){

//代码实现

}

}

这上方法签名可以代替前面的方法签名,但需要注意上面的类型形参S,它也是仅用了一次,没有其它参数类型,方法返回值类型依赖于它,那类型形参S就没有必要存在.即可以用通配符来代替S

     



使用通配符比显示声明类型形参更加清晰准确,所以在可能的情况下使用通配符更好.

类型通配符与显示志明类型形参还有一个显著的区别:

类型通配符即可以方法签名中定义形参的类型,也可以于定义变量的类型,但泛型方法中类型形参必须在对应方法中显示声明.

回复 使用道具 举报
泛型的好处就是把运行器的问题转移到了编译期。当你在一个集合上加泛型就等于告诉编译器这个集合中的元素只能是指定的那个泛型的类型,如果你添加的元素不是指定的泛型那么编译器就报错。当编译过后泛型就被擦除了。
由于上面的size方法是无泛型的方法,所以上面的两种方式是一样的。
回复 使用道具 举报
顶楼上!另外,简单介绍一下其作用:
类型Pair<?>有方法如下:
? getFirst()
void setFirst(?)
getFirst的返回值只能赋给一个Object。setFirst方法不能被调用,甚至不能用Object调用。Pair<?>和Pair的本质不同在于:可以用任意的Object对象调用原始的Pair类的setFirst()方法。
为什么要使用这样脆弱的类型?它对于许多简单的操作非常有用。例如,下面这个方法将用来测试一个pair是否包含了指定的对象,它不需要实际的类型。
    public static boolean hasNulls(Pair<?> p){
        return p.getFirst() == null || p.getSecond() == null;
    }
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马