定义

Java中的泛型在JavaSE5中引入。

所谓泛型,即参数化类型。就是说,类型是以参数的方式传入泛型类。

例如:

ArrayList aaryList = new ArrayList();

那么,类型参数就是Integer。

缘由

为什么要引入泛型呢,得看在没有泛型的情况下会存在什么样的问题。看下面这个非常常见的例子:

ArrayList a = new ArrayList();

a.add(1);

a.add("2");

for(int i=0; i

{

String strTmp = (String)a.get(i);

}

点击运行,啊哦,ClassCastException!

看出来了吧,问题就是类型不安全,给你一个ArrayList,很难直接获取内部元素的类型,容易引发错误。

泛型设计中的坑

JavaSE5中怎么引入泛型呢?

原先没有泛型的时候使用方式是这样:

ArrayList a = new ArrayList();

如果老的方式直接不支持了,那么基于Java做得那么多类库咋办,岂不是没法直接迁移至新版本的jdk?

No, No, No~这样会损失很多用户~

算了算了,非泛型和泛型两种方式并存吧。

那么泛型怎么在以前的基础上加入呢?

想来想去,还是在编译器保证吧!最简单!

ok,存在什么问题呢?看个demo:

class GenericsA

{

T t = new T(); // Error

}

天真的我以为可以这么搞,然而我却被告知: Type parameter 'T' cannot be instantiated directly.

好吧,原来这个T只是个占位符而已,类型信息并不会在运行时保存!类型信息会被擦除!

类型擦除

泛型的类型信息会被擦除,因此不要奢想在泛型类内部利用类型信息做任何事情。

至于使用泛型类的地方,编译器来做类型检查,但是也不足够安全。

看个例子:

public static void main(String[] args) {

ArrayList arrayList = new ArrayList();

arrayList.add("A");

arrayList.add("C");

arrayList.add(3);

String tmp = (String)arrayList.get(2);

}

啊哦,又是ClassCastException。

别忘记,ArrayList内部没有类型信息,在把ArrayList转为ArrayList非泛型列表之后,连编译器也无法正常类型检查了!

类型边界

在编译器类型检查之前,泛型的类型信息会被擦除至某个边界。

普通泛型class ClassA{}中类型会被擦除至Object。

class A

{

T item;

public A(T item)

{

this.item = item;

}

void test()

{

//此处,item只能调用属于Obeject类的方法

}

}

通过泛型类型上设置边界,我们可以实现类型的限定:

class Animal{

void talk(){}

}

class B

{

T item;

public A(T item)

{

this.item = item;

}

void test()

{

//此处,item可以调用属于Animal类的方法

item.talk();

}

}

甚至,可以设置多个边界:

interface Eatable {void eat();}

interface Drinkable {void drink();}

class B

{

T item;

void test()

{

//此处,item可以调用属于Eatable和Drinkable的方法

//不过,前提是,item同时是Eatable和Drinkable

//(这里只能通过多个接口实现的方式,或者一个基类和多个接口的方式,因为你无法使一个类继承自多个父类)

}

}

通配符

所谓通配符,作用就是匹配多种类型。

1. 上界通配符:   < ? extends B >

意思是,可以匹配类型A及其所有子类,即类型的上界是B,无下界。

举例子:

class A

{

public void print()

{

System.out.println("A");

}

}

class B extends A

{

@Override

public void print()

{

System.out.println("B");

}

}

class C extends B

{

@Override

public void print()

{

System.out.println("C");

}

}

class MyArrayList extends ArrayList extends B>

{

}

那么MyArrayList可以被赋值时:

MyArrayList myArrayList = new ArrayList(); //ERROR

MyArrayList myArrayList = new ArrayList(); //OK

MyArrayList myArrayList = new ArrayList(); //OK

再来看下元素读写情况。

编译器内心独白:

>>>> 既然设了上界通配符,那么我MyArrayList中的元素实际类型可能为B和B的任何子类,那么为了确保类型安全,只有同时继承自B和所有B的子类的类型才能add。

>>>> 嗯?好像没有任何一种类型可用满足以上条件。

>>>> 好吧,上界通配符泛型中,myArrayList不接受add方法。

>>>> 哦,对了,任何以泛型类型为参数的方法我都不接受!

好吧,经历了编译器的内心一番搏斗,所有以泛型类型为参数的方法都没法使用了:

myArrayList.add(new B()); //ERROR

myArrayList.add(new C()); //ERROR

myArrayList.set(0, new B()); //ERROR

但是,get()、remove()方法等方法还是可以用的。

2. 下界通配符  ? super B

意思是,可以匹配类型B及其所有基类,即类型的下界是B,上界是Object。

接着举例子:

class MyArrayList extends ArrayList super B>

{}

那么:

MyArrayList myArrayList = new ArrayList(); //OK

MyArrayList myArrayList = new ArrayList(); //OK

MyArrayList myArrayList = new ArrayList(); //ERROR

MyArrayList myArrayList = new ArrayList(); //OK

上至Object,下至B,所有的实例都可以赋值给泛型为的myArrayList。

再次看下元素读写情况。

编译器:

>>>> 既然设了下界通配符,那么我MyArrayList中的元素实际类型可能为B和B的任何父类,那么为了确保类型安全,只有同时是B以及B的所有父类的类型实例才能add。

>>>> 想一下,哪些类型符合条件呢?恩,好像所有B和B子类的实例都满足条件。例如。new B()既是B又是Object,new C()一样可以向上转型至B和Obejct....

>>>> 当然,所有B及其子类的实例都可以add进去。

>>>> 那么,get方法?

>>>> myArrayList内部可能的类型那么多(B及其所有父类),get的返回值类型咋办呢,算了,用通用的Object吧,真实类型让那些码农自己判断去吧!

java泛型详解_Java泛型详解(透彻)相关推荐

  1. java泛型常用特点_Java泛型详解

    对java的泛型特性的了解仅限于表面的浅浅一层,直到在学习设计模式时发现有不了解的用法,才想起详细的记录一下. 本文参考java 泛型详解.Java中的泛型方法. java泛型详解 1. 概述 泛型在 ...

  2. java合法的数组声明_Java数组详解

    Java数组详解 数组详解 1.数组概述 数组是相同类型数据的有序集合 每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们 2.数组声明和创建 ①数组声明形式 dataType[] a ...

  3. java 接口的泛型方法_Java泛型/泛型方法/通配符/泛型接口/泛型泛型擦出

    从JDK1.5以后引入了三大常用新特性:泛型.枚举(enum).注解(Annotation).其中JDK1.5中泛型是一件非常重要的实现技术,它可以帮助我们解决程序的参数转换问题.本文为大家详细介绍一 ...

  4. java 泛型集合应用_Java泛型集合的应用和方法

    展开全部 泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以62616964757a686964616fe78988e69d8331333 ...

  5. java 怎么为泛型参数赋值_Java泛型讲解

    1. 概述在引入泛型之前,Java类型分为原始类型.复杂类型,其中复杂类型分为数组和类.引入范型后,一个复杂类型 就可以在细分成更多的类型. 例如原先的类型List,现在在细分成List, List等 ...

  6. java泛型与接口_Java泛型用于方法,类和接口

    什么是泛型? 型就是数据类型参数化.就是说原本定死的数据类型像方法中的形参一样,数据是不确定的,使用的时候由人传进去,泛型就是这样,数据类型不确定了.使用的时候再确定就可以了. 泛型的特点 是JDK1 ...

  7. java泛型类的构造函数_java泛型,泛型类详解

    之前给大家介绍了一下java泛型集合方面的内容,下面要给大家介绍的就是泛型类方面的知识,一起通过简单的文章来进行一下了解吧. 泛型类 除了能够定义泛型集合之外,还能够直接限定泛型类的类型参数. 语法格 ...

  8. java list取值_Java集合详解

    一.集合的由来 通常,我们的程序需要根据程序运行时才知道创建多少个对象.但若非程序运行,程序开发阶段,我们根本不知道到底需要多少个数量的对象,甚至不知道它的准确类型.为了满足这些常规的编程需要,我们要 ...

  9. java 枚举使用例子_Java枚举详解及使用实例(涵盖了所有典型用法)

    在实际编程中,往往存在着这样的"数据集",它们的数值在程序中是稳定的,而且"数据集"中的元素是有限的. 例如星期一到星期日七个数据元素组成了一周的"数 ...

最新文章

  1. Python使用matplotlib可视化散点图、使用seaborn中的lmplot函数使用多子图可视化不同分组的散点图最优拟合线性回归曲线
  2. CloudStack4.1.1升级CloudPlatForm4.2.0实践手册
  3. 微信小程序【腾讯云开发】创建并上线小程序项目(涉及-数据库操作)
  4. TCP/IP详解学习笔记(2)-数据链路层
  5. Scala-2.13.0 安装及配置
  6. CF1267G-Game Relics【数学期望,dp】
  7. intent几种传值数组、对象、集合(Array,Object,List)
  8. 水平方向的算子检测竖直边缘理解
  9. 重启sql server 服务
  10. 第二次 HDOJ 1003
  11. const int * pi/int * const pi的区别
  12. Java基础 IO流——第三部分
  13. exchange server 2010 OWA 附件功能只支持IE浏览器
  14. ztree 后台异步加载_ztree 异步加载示例
  15. Premiere银色金属玻璃质感logo标志片头AE模板mogrt
  16. 走马观花-浪里跳-学习英文
  17. 认证 (authentication) 和授权 (authorization)小记
  18. mybatis拦截器实现update之前根据pk字段校验数据有效性
  19. udev (简体中文)
  20. 恒星物联 窨井盖安全监测系统方案 智慧井盖 井盖状态监测

热门文章

  1. 数据库高并发解决方案(一)查询优化
  2. Android 启动APP时黑屏白屏的三个解决方案
  3. 在使用Navicat for MySQL 出现 异常“You have an error in your SQL syntax......“
  4. vue-cli项目中单文件组件引入bootstrap.js异常的解决方案
  5. 我可以在目录中放入多少个文件?
  6. 升级win11系统需要预留多少磁盘空间 Windows11系统盘需要多少空间的介绍
  7. 计算当前时间往加N天后的时间,Date,SimpleDateFormat,Calendar
  8. 可见的轮廓线用虚线绘制_CAD制图初学入门教程:CAD软件中如何绘制轴测图?
  9. boost 安装_Win10 + VS2019 编译安装 Boost
  10. 手机按三角返回页面上一页_小猿圈微信小程序跳转页面都有哪些?