黑马程序员技术交流社区

标题: 泛型限定<? extends T> 和 <? super T>在什么时候使用 [打印本页]

作者: long362144768    时间: 2013-12-12 23:53
标题: 泛型限定<? extends T> 和 <? super T>在什么时候使用
本帖最后由 long362144768 于 2013-12-13 19:20 编辑

       研究很久,就是研究不会,请教大神!最好是通俗一点。
作者: Kyle    时间: 2013-12-13 00:08
设置泛型对象的上限使用extends,表示参数类型只能是该类型或该类型的子类:
声明对象:类名<? extends 类> 对象名
定义类:类名<泛型标签 extends 类>{}

设置泛型对象的下限使用super,表示参数类型只能是该类型或该类型的父类:
声明对象:类名<? super 类> 对象名称
定义类:类名<泛型标签 extends类>{}

作者: 熊猫86    时间: 2013-12-13 00:25
“?”为通配符,<? extends T>是向上限制,即限定最大的范围是T类,也可以是其子类;<? super T>是向下限制,即限定最小的范围是T类,也可以是其父类。
举个例子,个人认为这个形式在new出的对象有多态时会用到:
Vector<? extends Number> x = new Vector<Integer>();
Vector<? super Integer> x = new Vector<Number>();
这两个其实主要还是看你的侧重点是想让其范围更加开阔还是让其别超出一定范围。
作者: long362144768    时间: 2013-12-13 13:45
我的意思是,这两个应用在什么场合,举点带代码的小例子,什么时候用<? extends T>,什么时候用<? super T>,
作者: 刘渝灵    时间: 2013-12-13 16:26
本帖最后由 刘渝灵 于 2013-12-13 16:29 编辑

泛型限定,上限:? extends E 下限:? super E.
往容器中存入元素时会用到上限,从容器中取出元素时会用到下限(父类类型接收子类引用)。
API Collection框架中用到上,下限的例子:ArrayList中addAll(Collection<? extends E> c);TreeSet中带比较器的构造方法:TreeSet(Comparator<? super E> c).例子说明:
  1. import java.util.ArrayList;
  2. import java.util.Comparator;
  3. import java.util.TreeSet;

  4. public class GenericDemo {
  5.         public static void main(String[] args) {
  6.                 method1();
  7.                 method2();
  8.         }

  9.         //addAll(Collection<? extends E> c),"? extends E"增加了扩展性,允许集合能存入E及其子类的对象。
  10.         public static void method1() {
  11.                 //创建存储Person类型元素的集合并添加2个元素
  12.                 ArrayList<Person> al1 = new ArrayList<Person>();
  13.                 al1.add(new Person());
  14.                 al1.add(new Person());
  15.                 //创建存储Student类型元素的集合并添加2个元素
  16.                 ArrayList<Student> al2 = new ArrayList<Student>();
  17.                 al2.add(new Student());
  18.                 al2.add(new Student());
  19.                 //将集合al2整体添加进集合al1中
  20.                 al1.addAll(al2);               
  21.         }
复制代码

其实能上下进行限定根本的原因我觉得就是多态。

作者: 刘渝灵    时间: 2013-12-13 16:30
回复的代码行数好像有限制,补全:
  1. public static void method2() {
  2.                
  3.                 //元素存入TreeSet时,会先进行比较,其元素是有指定顺序的。
  4.                 //我们这里在构造时指定比较器
  5.                 //观察下面3个比较器,比较的功能是重复的,用父类比较器即可。
  6.                 //也即可以写成:TreeSet<Person> ts1 = new TreeSet<Person>(new PersonCompImpl());
  7.                 //TreeSet<Student> ts2 = new TreeSet<Student>(new PersonCompImpl()());
  8.                 //TreeSet<Worker> ts3 = new TreeSet<Worker>(new PersonCompImpl()());
  9.                 TreeSet<Person> ts1 = new TreeSet<Person>(new PersonCompImpl());
  10.                 ts1.add(new Person());
  11.                 ts1.add(new Person());
  12.                 //创建存储Student类型元素的集合,并指定比较器
  13.                 TreeSet<Student> ts2 = new TreeSet<Student>(new StudentCompImpl());
  14.                 ts2.add(new Student());
  15.                 ts2.add(new Student());
  16.                 //创建存储Person类型元素的集合,并指定比较器
  17.                 TreeSet<Worker> ts3 = new TreeSet<Worker>(new WorkerCompImpl());
  18.                 ts3.add(new Worker());
  19.                 ts3.add(new Worker());
  20.                
  21.         }       
  22. }
  23. class Person{
  24.         //省略name,age属性,set,get方法
  25.         }
  26. }
  27. class Student extends Person{}
  28. class Worker extends Person{}

  29. class PersonCompImpl implements Comparator<Person>{
  30.         @Override
  31.         public int compare(Person arg0, Person arg1) {               
  32.                 //这里会调用arg0,arg1的getName(),getAge()方法进行比较
  33.                 return 0;
  34.         }       
  35. }
  36. class StudentCompImpl implements Comparator<Student>{
  37.         @Override
  38.         public int compare(Student arg0, Student arg1) {
  39.                 //这里也会调用arg0,arg1的getName(),getAge()方法进行比较
  40.                 return 0;
  41.         }       
  42. }
  43. class WorkerCompImpl implements Comparator<Worker>{
  44.         @Override
  45.         public int compare(Worker arg0, Worker arg1){
  46.                 //这里也会调用arg0,arg1的getName(),getAge()方法进行比较
  47.                 return 0;
  48.         }       
  49. }
复制代码

作者: 冬天的热带鱼    时间: 2013-12-13 17:35
import java.util.*;
/*
泛型的限定:
? extends E:可以接收E类型或者E的子类型。上限。(向上限定)
? super E:可以接收E类型或者E的父类型。下限。(向下限定)
*/

class Person
{
        private String name;
        Person(String name)
        {
                this.name = name;
        }
        public String getName()
        {
                return name;
        }
}
class Student extends Person
{
        Student(String name)
        {
                super(name);
        }
}

class GenericDemo
{
        public static void main(String[] args)
        {
                ArrayList<Person> al = new ArrayList<Person>();
                al.add(new Person("abc01"));
                ArrayList<Student> al1 = new ArrayList<Student>();
                al1.add(new Student("abc001"));

                printColl(al);
                printColl(al1);
         }
        //<? extends T>的用法
        //可以接收Person或者子类的对象。
        public static void printColl(ArrayList<? extends Person> al)
        {
                Iterator<? extends Person> it = al.iterator();
                while(it.hasNext())
                {
                        System.out.println(it.next().getName());
                }
        }

}
//因为Student向上的父类有Object,所以在上面的例子中没有具体的实现下面的方法。
//<? super T>的用法
        //此处可以接收Student或者其父类的对象。
        public static void printColl2(ArrayList<? super Student> al)
        {
                Iterator<? super Student> it = al.iterator();
                while(it.hasNext())
                {
                        System.out.println(it.next().getName());
                }
        }



作者: 史超    时间: 2013-12-13 17:42
这两个泛型类型
? extends xxx 只能用于方法传参,因为jdk能够确定传入为xxx的子类,返回只能用Object类接收
? supper xxx 只能用于方法返回,jdk能够确定此类的最小继承边界为xxx,只要是这个类的父类都能接收,但是传入参数无法确定具体类型,只能接受null的传入。
? 既不能用于方法参数传入,也不能用于方法返回。





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2