黑马程序员技术交流社区

标题: 我对泛型类的理解,思路可能和书上不一样 [打印本页]

作者: 至尊幽蓝    时间: 2015-8-31 13:13
标题: 我对泛型类的理解,思路可能和书上不一样
本帖最后由 至尊幽蓝 于 2015-8-31 23:30 编辑

      下面是我对泛型类的理解,思考的角度可能和书本上的有些不同,但很坚定。
      自Java1.5版本泛型出现,集合类应该是被重新书写了,由普通类改写成了泛型类。
泛型类的使用过程包括的步骤有:泛型类引用的声明,泛型类对象的创建以及引用指向对象。作此说明是为了下面方便说明我对泛型的理解。

1.声明泛型类引用时,需在类名后指出泛型指代的类型,注意我说的是指出,不是指明。这里指出的意思是有<…>这组符号,放个”?”或”?extends(super) XXX”也算指出了。如果不指出,也可以编译运行,并且未做出指出的泛型可以指代任意类型,但会有警告。集合类(泛型版本)就表现出这个特性了。
举例:(String只是举例)
MyClass<String> mc;    //可编译运行,无警告,mc中相应的泛型只能使用String
MyClass     mc;         //可编译运行,有警告,mc中相应的泛型可以指代任意类型

2.创建泛型类对象时,需要在类名后指明泛型指代的类型,注意这里我说的是指明,”?”或”? extends(super) XXX”不算指明。就是有<String>,尖括号中的泛型必须具体到某一种类型。如果不指出也会有警告,但同样也能编译运行,并且未指出的泛型可以指代任意类型,但如果指出了却未指明,即”?”或”? extends(super) XXX”,就不是警告了,而是错误。
举例:(String只是举例)
new MyClass<String>();     //可编译运行,无警告,其中相应的泛型只能使用String
new MyClass();     //可编译运行,有警告,其中相应的泛型可以指代任意类型
new       MyClass<?>();             //错误。

3.泛型引用指向泛型对象,
      1)未指出泛型类型的引用,可以指向泛型类型被指明为任意类型的泛型对象,即“MyClass mc; ” 声明的mc可以指向new MyClass()   ,new MyClass< XXX>(),  XXX可以为具体到某一种类型的任意类型。
      2)MyClass<String> mc; 声明的mc只能指向new MyClass(),new MyClass< String >(),
在这里,new MyClass() 被自动转换成了String,此转换是未经检查的,
当new MyClass()不是String类型时,一旦调用mc的String方法时,就会抛出转换异常。
      3) MyClass<?> mc;  中的mc可以指向的泛型类和“MyClass mc; ”中的mc可以指向的类型一样,只是这样声明不会出现警告。
      4)MyClass<? extends  Father> mc; 声明的mc可以指向new MyClass() 和new  MyClass<XXX >(),  XXX是Father及其子类中具体到某一种的类。
在这里,new MyClass()被自动转换成了Father(eclipse中写的是转换成“? extends  Father”,但给出的方法只是Father的方法。此转换是未经检查的,
当new MyClass()不是Father类型时,一旦调用mc的Father方法时,就会抛出转换异常。
      5)MyClass<? super Father>  mc;  同4)相似,只是XXX是Father及其父类。

      关于引用指向对象:
1)MyClass<? extends  Father> mc =new MyClass<Son>();   是mc指向了后面创建的对象;
2)另一种情况,定义方法:
Void  show(MyClass<?  extends Father>   mc){}   这里也是声明了一个引用,当使用该方法时,就是让这个引用指向了相应的对象,所以在使用该方法时,其中的参数mc只能是上面4)所包括的类型。
举例:
ArrayList的一个构造方法的定义:ArrayList(Collection<? extends Father>  c){…}  该构造方法用到的Father是定义ArrayList<E>时其中的E。
下面是该方法的使用即调用该构造方法创建一个ArrayList:
Student和Worker均是Person的子类:
1                ArrayList<Student> slis=new ArrayList<Student>();
2                LinkedList<Worker> wlis=new LinkedList<Worker>();
3                ArrayList<Person> plis1=new ArrayList<Person>(slis);
4                ArrayList<Person> plis2=new ArrayList<Person>(wlis);
5                ArrayList<String> ms=new ArrayList<String>();                                        //String不是Person的子类
6//                ArrayList<Person> plis3=new ArrayList<Person>(ms);               
7                LinkedList<Object> mo=new LinkedList<Object>();                                //Object是Person的父类,但此处要子类
8//                ArrayList<Person> plis4=new ArrayList<Person>(mo);
第3行和第4行定义ArrayList时,用了上面的构造方法,其中的E是Person,所以括号中的Collection<...>中的泛型必须是Person或其子类,正如第1行和第2行定义的,slis中的Student和wlis中的Worker都是Person的子类,所以第3和第4行没问题;但是第6行和第8行会出错,因为String和Object都不是Person的子类。




作者: 至尊幽蓝    时间: 2015-8-31 13:36
本帖最后由 至尊幽蓝 于 2015-8-31 23:32 编辑

最后一个例子,忘了Collectin是接口了,应该用一个可实例化的集合。
作者: 至尊幽蓝    时间: 2015-8-31 20:48
沉的好快
作者: 夕阳游子    时间: 2015-8-31 21:01
感谢楼主分享
作者: 至尊幽蓝    时间: 2015-8-31 23:39
夕阳游子 发表于 2015-8-31 21:01
感谢楼主分享

内容又更新了




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