java泛型上下限
前言:
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泛型上下限的更多相关文章
- Java泛型的历史
为什么Java泛型会有当前的缺陷? 之前的章节里已经说明了Java泛型擦除会导致的问题,C++和C#的泛型都是在运行时存在的,难道Java天然不支持“真正的泛型”吗? 事实上,在Java1.5在200 ...
- 浅析Java 泛型
泛型是JavaSE5引入的一个新概念,但是这个概念在编程语言中却是很普遍的一个概念.下面,根据以下内容,我们总结下在Java中使用泛型. 泛型使用的意义 什么是泛型 泛型类 泛型方法 泛型接口 泛型擦 ...
- Java:泛型基础
泛型 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚很多! 解决这种限制的 ...
- java泛型基础
泛型是Java SE 1.5的新特性, 泛型的本质是参数化类型, 也就是说所操作的数据类型被指定为一个参数. 这种参数类型可以用在类.接口和方法的创建中, 分别称为泛型类.泛型接口.泛型方法. Ja ...
- 使用java泛型设计通用方法
泛型是Java SE 1.5的新特性, 泛型的本质是参数化类型, 也就是说所操作的数据类型被指定为一个参数. 因此我们可以利用泛型和反射来设计一些通用方法. 现在有2张表, 一张user表和一张stu ...
- 关于Java泛型的使用
在目前我遇到的java项目中,泛型应用的最多的就属集合了.当要从数据库取出多个对象或者说是多条记录时,往往都要使用集合,那么为什么这么使用,或者使用时有什么要注意的地方,请关注以下内容. 感谢Wind ...
- 初识java泛型
1 协变数组类型(covariant array type) 数组的协变性: if A IS-A B then A[] IS-A B[] 也就是说,java中的数组兼容,一个类型的数组兼容他的子类类型 ...
- 【Java心得总结四】Java泛型下——万恶的擦除
一.万恶的擦除 我在自己总结的[Java心得总结三]Java泛型上——初识泛型这篇博文中提到了Java中对泛型擦除的问题,考虑下面代码: import java.util.*; public clas ...
- 【Java心得总结三】Java泛型上——初识泛型
一.函数参数与泛型比较 泛型(generics),从字面的意思理解就是泛化的类型,即参数化类型.泛型的作用是什么,这里与函数参数做一个比较: 无参数的函数: public int[] newIntAr ...
随机推荐
- 弄清 CSS3 的 transition 和 animation
弄清 CSS3 的 transition 和 animation transition transition 属性是 transition-property, transition-duration, ...
- Unity中的Matrix4x4类
物体平移旋转一般变换底层都是用矩阵来表示的,一般不会用到这个类.有时候需要一些世界坐标与局部坐标转换的时候,可能就要用到了. //创建平移 旋转 缩放矩阵 可以理解为一个坐标系(不知道对不对..) M ...
- linux platform设备与驱动
struct platform_driver { int (*probe)(struct platform_device *); int (*remove)(struct platform_devic ...
- APP设计资源
在开发独立客户端时,需要一些不同尺寸的图标和图片,统计如下. APP 图标 ICON iOS:(主要需要这三类图标) 58x58 87x87 (Spotlight & Settings) 80 ...
- iOS8沙盒路径的变化
iOS8中的的沙盒路径发生了变化 之前是这样的路径,通过NSHomedictionary()获取的家路径 /Users/wupeng/Library/Application Support/iPhon ...
- MAC显示文件夹路径
MAC显示文件夹路径 终端命令 1.显示路径:defaults write com.apple.finder _FXShowPosixPathInTitle -bool TRUE;killall Fi ...
- JS 的事件委托机制
以前写上图所示的鼠标点击触发事件,一般都是用如下所示的给每一个表示列表的标签绑定一个click事件(演示用的例子的框架是React): 毫无疑问,这样是比较繁琐的,以后维护修改改个函数名什么的还不方便 ...
- 2016/11/16 周三 <使用LocalStore记住用户密码方法示例>
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...
- 多文档上传(upload multiple documents)功能不能使用怎么办?
问题描述: 在SharePoint 2010的文档库里选择documents标签,然后选择upload document下拉菜单,你会发现upload multiple documents那个按钮是灰 ...
- EF 连接sql2000
正常连接会提示版本低 可以先用ef连接高版本的sql然后新建好EDMX文件后,在右键xml方式打开,把ProviderManifestToken="2008" 改为2000 然后再 ...