前言:

  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. 浅说如何制作javascript类库

    理论 对于静态的类来说,JavaScript 对象直接量就已经够用了,但使用继承和实例来创建经典的类往往更有帮助. JavaScript 是基于原型的编程语言,并没有包含内置类的实现. 但通过Java ...

  2. Android应用-听听

    听听是一款记歌词音乐播放器android应用. 功能特点:1.搜索网络歌词.2.本地音乐分类播放.3.离线保存网络歌词.4.页面整洁干净,风格清新. 下载APP 屏幕截图:        

  3. UVA103 dp基础题,DAG模型

    1.UVA103 嵌套n维空间 DAG模型记忆化搜索,或者 最长上升子序列. 2.dp[i]=max( dp[j]+1),(第i个小于第j个) (1) //DAG模型记忆化搜索 #include< ...

  4. nginx android app 慢网络请求超时

    最近遇到了android 在慢网络下面请求服务器报 java.net.SocketException: recvfrom failed: ECONNRESET (Connection reset by ...

  5. Mariadb数据库设置及操作 一主多从 备份还原(实测笔记)

    环境: 系统硬件:vmware vsphere (CPU:2*4核,内存2G,双网卡) 系统版本:CentOS-7-x86_64-Minimal-1611.iso 数据库版本信息 : 10.1.20- ...

  6. Python之路Day14--html

    本节内容: 一.HTML 二.CSS 三.JS HTML 1.一套规则,浏览器认识的规则. 2.开发者: 学习Html规则 开发后台程序: - 写Html文件(充当模板的作用) ****** - 数据 ...

  7. Base64 转换 %2B 变 空格 解决

    //此方法转换会转换出错 deString.ServerUrlDecode().Replace(" ", "+") //换此方法完美解决 HttpUtility ...

  8. [译]MVC网站教程(三):动态布局和站点管理

    目录 1.   介绍 2.   软件环境 3.   在运行示例代码之前(源代码 + 示例登陆帐号) 4.   自定义操作结果和控制器扩展 1)   OpenFileResult 2)   ImageR ...

  9. Docker:镜像操作和容器操作

    镜像操作 列出镜像: $ sudo docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE hello-world latest 0a6b ...

  10. Windows Azure Storage (6) Windows Azure Storage之Table

    <Windows Azure Platform 系列文章目录> 最近想了想,还是有必要把Windows Azure Table Storage 给说清楚. 1.概念 Windows Azu ...