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 ...
随机推荐
- ZooKeeper个人笔记客户端watcher和AsycCallback回调
每一个Watcher具有如下属性: 1.KeeperState 2.EventType 3.path 4.process(WatchedEvent evnet)回掉方法 Watcher干嘛的?用户监听 ...
- Spark ZooKeeper数据恢复
Spark使用ZooKeeper进行数据恢复的逻辑过程如下: 1.初始化:创建<CuratorFramwork,LeaderLatch,LeaderLatchListener>用于选举 创 ...
- Django框架学习
两个月前学习的Django框架,写了个简易婚恋调查网站,代码就懒得全贴了,有两张图记录下
- 【BZOJ1911】[Apio2010]特别行动队 斜率优化DP
想了好久啊....——黑字为第一次更新.——这里是第二次更新,维护上下凸包据题而论,第一种方法是化式子的方法,需要好的化式子的方法,第二种是偏向几何,十分好想,纯正的维护凸包的方法,推荐. 用了我感觉 ...
- WPF-系统托盘
WPFSystemTray.cs public class WPFSystemTray { /// <summary> /// 设置系统托盘 /// </summary> // ...
- ssm简单配置
MyBatis 是一个可以自定义SQL.存储过程和高级映射的持久层框架. MyBatis 摒除了大部分的JDBC代码.手工设置参数和结果集重获. MyBatis 只使用简单的XML 和注解来配置和映射 ...
- redis的面试题,没答出来,直接被pass
redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略.redis 提供 6种数据淘汰策略: volatile-lru:从已设置过期时间的数据集(server.db[i].expire ...
- poj2833
//poj2833优先队列.数据量太大,而且没有必要全部排序. //优先队列 //* #include<iterator> #include <stdio.h> #includ ...
- MYSQL删除重复数据
delete from co_jobinformation cwhere c.name in (select cc.name from co_jobinformation cc group by ...
- php-(/usr/local/php)安装编译选项
./configure \ --prefix=/usr/local/php \ --with-config-file-path=/usr/local/php/etc \ --enable-fpm \ ...