前言:

  java的泛型上下限不是很好理解,尤其像我这种菜鸡。反反复复看了好几遍了...,真是...

一、简单的继承体系

class Person{}

class Student extends Person{}

class Worker extends Person{}

二、泛型上限(extends 关键字)

public static void upperBound(List<? extends Person> list, Person p){
//正确,因为null没有类型信息
list.add(null);
//错误,因为list的参数类型可能是Person的子类
list.add(p);①
//成功获取
if(list.size() > 0){
Person pp = list.get(0);②
}
}

  ①处的错误在于list的参数类型是不确定的,其参数类型可能是 Person的子类,子类集合(List)不能添加父类的元素。测试如下:

public static void testUpperBound(){
ArrayList<Student> slist = new ArrayList<Student>();
Person p = new Person();
upperBound(slist, p);//无法添加成功
}

  如何解决泛型上限添加问题,可以使用泛型方法,如下:

public static <T extends Person> void upperBound2(List<T> list, T p){
list.add(p);
}
public static void testUpperBound2(){
ArrayList<Person> plist = new ArrayList<Person>();
Person p = new Person();
Student s = new Student();
upperBound2(plist, p); upperBound2(plist, s);
}

  也就是说,使用泛型上限add方法时,集合参数类型 和 元素参数类型 要一致,这样添加的时候才不会有矛盾。看一下eclipse中对upperBound2(plist, s);这个函数调用的提示,如下:

  可见,T类型最终会解析为 泛型的最上限类型,Student s相应的向上转型。

  接着说 ② 处,为什么能获取成功呢?泛型上限嘛,至少上限的类型是确定的,所有的上限类型的子类都可以进行向上转型,自然获取是不成问题了。

三、泛型的下限

public static void lowerBound(List<? super Student> list){
Person var = new Person();
//错误,list的参数类型可能是 Student,这样就不能添加父类Person了,所以 变量var的类型 必须是 Student或者 Student的子类
list.add(p);①
//正确
Student s = new Student();
list.add(s);
}
public static void testlowerBound(){
ArrayList<Person> list = new ArrayList<Person>();
lowerBound(list);
}

  ①处添加失败,告诉我们,泛型下限使用add方法添加元素时,元素的参数类型必须是 下限 或者 下限的子类型。否则会出现子类集合添加父类元素。

public static void lowerBound2(List<? super Person> list){
Person p = new Person();
list.add(p);
//获取,不能编译
Person as = list.get(0);①
}
public static void testlowerBound2(){
ArrayList<Person> list = new ArrayList<Person>();
lowerBound2(list);
}

  ①处获取失败了,我们看一下eclipse提示我们该怎么办?

  将 第二个方法 将"as"的类型更改为"Object"  和 泛型的下限 结合一下考虑一下,add(e)方法在正确添加后,都会成为Object对象,在使用get(index)方法时,会转换为

? super Person类型(可能是Person类型,也可能是Person的父类类型,甚至是Object),执行Person as = list.get(0),那么就有了 向下转型。java中无法保证向下转型是安全的。所以①处不能编译。

四、泛型上限最常见的一个应用

List<Person> plist = new ArrayList<Person>();
List<Student> slist = new ArrayList<Student>(); plist.addAll(slist);

五、泛型下限最常见的一个应用

Set<Student> set = new TreeSet<Student>(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return 0;
}
});

六、泛型上下限一个综合的例子

  注:个人瞎掰的...,就是将上面两个例子结合在一起!

Set<Person> set = new TreeSet<Person>(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return 0;
}
});
List<Student> slist = new ArrayList<Student>();
List<Worker> wlist = new ArrayList<Worker>();
set.addAll(slist);
set.addAll(wlist);

  接下来,研究一下泛型的擦除...

java泛型上下限的更多相关文章

  1. Java泛型的历史

    为什么Java泛型会有当前的缺陷? 之前的章节里已经说明了Java泛型擦除会导致的问题,C++和C#的泛型都是在运行时存在的,难道Java天然不支持“真正的泛型”吗? 事实上,在Java1.5在200 ...

  2. 浅析Java 泛型

    泛型是JavaSE5引入的一个新概念,但是这个概念在编程语言中却是很普遍的一个概念.下面,根据以下内容,我们总结下在Java中使用泛型. 泛型使用的意义 什么是泛型 泛型类 泛型方法 泛型接口 泛型擦 ...

  3. Java:泛型基础

    泛型 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚很多! 解决这种限制的 ...

  4. java泛型基础

    泛型是Java SE 1.5的新特性, 泛型的本质是参数化类型, 也就是说所操作的数据类型被指定为一个参数. 这种参数类型可以用在类.接口和方法的创建中, 分别称为泛型类.泛型接口.泛型方法.  Ja ...

  5. 使用java泛型设计通用方法

    泛型是Java SE 1.5的新特性, 泛型的本质是参数化类型, 也就是说所操作的数据类型被指定为一个参数. 因此我们可以利用泛型和反射来设计一些通用方法. 现在有2张表, 一张user表和一张stu ...

  6. 关于Java泛型的使用

    在目前我遇到的java项目中,泛型应用的最多的就属集合了.当要从数据库取出多个对象或者说是多条记录时,往往都要使用集合,那么为什么这么使用,或者使用时有什么要注意的地方,请关注以下内容. 感谢Wind ...

  7. 初识java泛型

    1 协变数组类型(covariant array type) 数组的协变性: if A IS-A B then A[] IS-A B[] 也就是说,java中的数组兼容,一个类型的数组兼容他的子类类型 ...

  8. 【Java心得总结四】Java泛型下——万恶的擦除

    一.万恶的擦除 我在自己总结的[Java心得总结三]Java泛型上——初识泛型这篇博文中提到了Java中对泛型擦除的问题,考虑下面代码: import java.util.*; public clas ...

  9. 【Java心得总结三】Java泛型上——初识泛型

    一.函数参数与泛型比较 泛型(generics),从字面的意思理解就是泛化的类型,即参数化类型.泛型的作用是什么,这里与函数参数做一个比较: 无参数的函数: public int[] newIntAr ...

随机推荐

  1. [BZOJ1562][NOI2009] 变换序列

    Description Input Output Sample Input 5 1 1 2 2 1 Sample Output 1 2 4 0 3 HINT 30%的数据中N≤50:60%的数据中N≤ ...

  2. VS调式显示问题

    调式时,发现与以前的显示不太一样,虽然也能看到结果,但不是很方便,后来网上查找到与VS中的一个文件被修改有关. 找个别人安装过的VS2005,替换Common7\Packages\Debugger\a ...

  3. JAVA使用SAX解析XML文件

    在我的另一篇文章(http://www.cnblogs.com/anivia/p/5849712.html)中,通过一个例子介绍了使用DOM来解析XML文件,那么本篇文章通过相同的XML文件介绍如何使 ...

  4. 【Telerik】<telerik:RadComboBox>导出列表数据

    近来在做项目,做到导出功能.使用<telerik:RadComboBox>的下拉框来实现导出部分或导出所有数据的功能.

  5. bzoj 2563: 阿狸和桃子的游戏

    开始写了一些东西但是后来浏览器挂了就没有存下来简直!!!!!!!!!!!!!QAQ 不想再写一遍了...总之是简单贪心. #include <iostream> #include < ...

  6. 转载:iOS开发之让你的应用“动”起来

    在iOS中随处都可以看到绚丽的动画效果,实现这些动画的过程并不复杂,今天将带大家一窥iOS动画全貌.在这里你可以看到iOS中如何使用图层精简非交互式绘图,如何通过核心动画创建基础动画.关键帧动画.动画 ...

  7. MUI框架---实现百度地图定位功能

    1 2 <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak= ...

  8. 通过修改i8042prt端口驱动中类驱动Kbdclass的回调函数地址,达到过滤键盘操作的例子

    同样也是寒江独钓的例子,但只给了思路,现贴出实现代码 原理是通过改变端口驱动中本该调用类驱动回调函数的地方下手 //替换分发函数 来实现过滤 #include <wdm.h> #inclu ...

  9. Struts2

    为什么要用Struts2? 这里列举一些Servlet的缺点: 1.每写一个servlet在web.xml中都要做相应的配置.如果有多很servlet,会导致web.xml内容过于繁多. 2.这样的结 ...

  10. Android图片资源

    title: 2016-5-5未命名文件 tags: UI适配,图片资源 grammar_cjkRuby: true --- 概述: 本文整理了Android开发中,图片资源的提供方式和使用方式.包括 ...