java泛型详解_Java泛型详解(透彻)
定义
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泛型详解(透彻)相关推荐
- java泛型常用特点_Java泛型详解
对java的泛型特性的了解仅限于表面的浅浅一层,直到在学习设计模式时发现有不了解的用法,才想起详细的记录一下. 本文参考java 泛型详解.Java中的泛型方法. java泛型详解 1. 概述 泛型在 ...
- java合法的数组声明_Java数组详解
Java数组详解 数组详解 1.数组概述 数组是相同类型数据的有序集合 每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们 2.数组声明和创建 ①数组声明形式 dataType[] a ...
- java 接口的泛型方法_Java泛型/泛型方法/通配符/泛型接口/泛型泛型擦出
从JDK1.5以后引入了三大常用新特性:泛型.枚举(enum).注解(Annotation).其中JDK1.5中泛型是一件非常重要的实现技术,它可以帮助我们解决程序的参数转换问题.本文为大家详细介绍一 ...
- java 泛型集合应用_Java泛型集合的应用和方法
展开全部 泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以62616964757a686964616fe78988e69d8331333 ...
- java 怎么为泛型参数赋值_Java泛型讲解
1. 概述在引入泛型之前,Java类型分为原始类型.复杂类型,其中复杂类型分为数组和类.引入范型后,一个复杂类型 就可以在细分成更多的类型. 例如原先的类型List,现在在细分成List, List等 ...
- java泛型与接口_Java泛型用于方法,类和接口
什么是泛型? 型就是数据类型参数化.就是说原本定死的数据类型像方法中的形参一样,数据是不确定的,使用的时候由人传进去,泛型就是这样,数据类型不确定了.使用的时候再确定就可以了. 泛型的特点 是JDK1 ...
- java泛型类的构造函数_java泛型,泛型类详解
之前给大家介绍了一下java泛型集合方面的内容,下面要给大家介绍的就是泛型类方面的知识,一起通过简单的文章来进行一下了解吧. 泛型类 除了能够定义泛型集合之外,还能够直接限定泛型类的类型参数. 语法格 ...
- java list取值_Java集合详解
一.集合的由来 通常,我们的程序需要根据程序运行时才知道创建多少个对象.但若非程序运行,程序开发阶段,我们根本不知道到底需要多少个数量的对象,甚至不知道它的准确类型.为了满足这些常规的编程需要,我们要 ...
- java 枚举使用例子_Java枚举详解及使用实例(涵盖了所有典型用法)
在实际编程中,往往存在着这样的"数据集",它们的数值在程序中是稳定的,而且"数据集"中的元素是有限的. 例如星期一到星期日七个数据元素组成了一周的"数 ...
最新文章
- Python使用matplotlib可视化散点图、使用seaborn中的lmplot函数使用多子图可视化不同分组的散点图最优拟合线性回归曲线
- CloudStack4.1.1升级CloudPlatForm4.2.0实践手册
- 微信小程序【腾讯云开发】创建并上线小程序项目(涉及-数据库操作)
- TCP/IP详解学习笔记(2)-数据链路层
- Scala-2.13.0 安装及配置
- CF1267G-Game Relics【数学期望,dp】
- intent几种传值数组、对象、集合(Array,Object,List)
- 水平方向的算子检测竖直边缘理解
- 重启sql server 服务
- 第二次 HDOJ 1003
- const int * pi/int * const pi的区别
- Java基础 IO流——第三部分
- exchange server 2010 OWA 附件功能只支持IE浏览器
- ztree 后台异步加载_ztree 异步加载示例
- Premiere银色金属玻璃质感logo标志片头AE模板mogrt
- 走马观花-浪里跳-学习英文
- 认证 (authentication) 和授权 (authorization)小记
- mybatis拦截器实现update之前根据pk字段校验数据有效性
- udev (简体中文)
- 恒星物联 窨井盖安全监测系统方案 智慧井盖 井盖状态监测
热门文章
- 数据库高并发解决方案(一)查询优化
- Android 启动APP时黑屏白屏的三个解决方案
- 在使用Navicat for MySQL 出现 异常“You have an error in your SQL syntax......“
- vue-cli项目中单文件组件引入bootstrap.js异常的解决方案
- 我可以在目录中放入多少个文件?
- 升级win11系统需要预留多少磁盘空间 Windows11系统盘需要多少空间的介绍
- 计算当前时间往加N天后的时间,Date,SimpleDateFormat,Calendar
- 可见的轮廓线用虚线绘制_CAD制图初学入门教程:CAD软件中如何绘制轴测图?
- boost 安装_Win10 + VS2019 编译安装 Boost
- 手机按三角返回页面上一页_小猿圈微信小程序跳转页面都有哪些?