Java 泛型程序设计
1. 泛型类
public class Pair<T>
{
private T first;
private T second;
public void setSecond(T second){...}
....
}
2. 泛型方法
class ArrAlg{
public static <T> T getMiddle(T... a){
return a[a.length/2];
}
}
3. 类型变量的限定
public static <T extends BoundingType1 & BoundingType2 ...> T min(T[] a)....
这表示T应该是BoundingType类型的子类型。T和绑定类型可以是类,也可以是接口 。一个类型变量或通配符可以有多个限定,但限定中之多只有一个类,这是因为单继承,当有多个限定时,基类要写在第一个,接口写在后面。
4. 原始类型,任何一个泛型类型,都自动提供一个原始类型,原始类型的名字就是删去类型参数后的类型名。例如Pair<T>, 原始类型就是Pair。
5. 泛型转换
- 虚拟机中没有泛型,只有普通的类和方法
- 所有的类型参数都用它们的第一个限定类型替换,没有写明限定类型就用Object
- 合成桥方法保持多态。
- 为保持类型安全性,必要时插入强制类型转换(例如调用泛型方法返回值)
5. 桥方法
假设有下列类继承了Pair<Date>,
class DateInterval extends Pair<Date>
{
public void setSecond(Date second){
....
}
}
实际擦除类型之后
class DateInterval extends Pair
{
public void setSecond(Date second){...}
//因为类型擦除,实际还存在一个继承于Pair类的方法,显然这是两个方法
public void setSecond(Object second){
//实际生成桥方法,这里会调用setSecond(Date seconde);即:
setSecond((Date)second);
}
}
当如下调用时 Pair<Date> pair = new DateInterval(...); pair.setSecond(aDate);。Pair类型只有一个方法setSecond(Object)。实际引用DateInterval类,因而将会调用DateInterval.setSecond(Object)。编译器为了调用最合适的方法,实际上生成了一个桥方法,如下 public void setSecond(Object second){ setSecond((Date) second) } 。
6. 约束与局限性
- 不能用基本类型实例化类型参数
- 运行时类型查询只适用于原始类型
- 不能创建参数化类型的数组,即不能
new Pair<String> [10] - 不能实例化类型变量,即不能使用 new T(...), new T[] 或T.class这类的表达式。可以通过反射实例化T但不能T.class.newInstance(); 可以如下设计API来实现。
public static <T> Pair<T> makePair(Class<T> cl){
try{
return new Pair<>(cl.newInstance(), cl.newInstance())
}catch(Exception e){return null;}
}
- 泛型类的静态上下文中不能引用类型变量,例如
private static T aData; 或者 public static T fun(){}都是错误的。 - 不能抛出或捕获泛型类的实例
7. 通配符
- 通配符限定: extends 、super
例:Pair<? extends Person>表示泛型Pair类型,它的参数是Person的子类。
在这种情况下,getter和setter区别,getter可以正常调用,但是setter不行,会产生编译错误,因为编译器不能确定要传入参数的类型,也没法代替。
?extends Person getFirst()
void setFirst(? extends Person)
反之,通配符的超类型限定: ?super Student
void setFirst(? super Student);
? super Student getFirst();
编译器虽然不知道setFirst的确切类型,但是可以用任意Student对象调用,而不能用Person对象调用。如果调用getFirst,返回的对象不能保证,只能赋给Object。
- 无限定通配符 Pair<?>
? getFirst();
void setFirst(?);
getFirst的返回值只能赋给一个Object, setFirst不能调用除非setFirst(null),对于一些简单操作非常有用,例如判定是否为null getFirst() == null
- 通配符捕获 可以通过泛型方法捕获通配符
Java 泛型程序设计的更多相关文章
- java泛型(一)、泛型的基本介绍和使用
现在开始深入学习java的泛型了,以前一直只是在集合中简单的使用泛型,根本就不明白泛型的原理和作用.泛型在java中,是一个十分重要的特性,所以要好好的研究下. 泛 型的定义:泛型是JDK 1.5的一 ...
- java泛型使用
泛型的解释 现在感觉泛型是一个值得学习的地方,就抽出时间来学习和总结一下泛型的使用. Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允 ...
- Java泛型一:基本介绍和使用
原文地址http://blog.csdn.net/lonelyroamer/article/details/7864531 现在开始深入学习java的泛型了,以前一直只是在集合中简单的使用泛型,根本就 ...
- java泛型 7 泛型的基本介绍和使用
现在开始深入学习Java的泛型了,以前一直只是在集合中简单的使用泛型,根本就不明白泛型的原理和作用.泛型在java中,是一个十分重要的特性,所以要好好的研究下. 一.泛型的基本概念 泛型的定义:泛型是 ...
- Java基础语法<十二> 泛型程序设计
1 意义 泛型程序设计意味着编写的代码可以被很多不同类型的对象所重用. 常见应用 : ArrayList 2 K T V E ? object等的含义 类型变量使用大写形式 E – Element ( ...
- Java核心技术第八章——泛型程序设计(1)
1.泛型程序设计 泛型程序设计意味着编写的代码可以被很多不同类型的对象所重用.例如:不希望为了聚集String和Integer对象分别设计不同的类.(个人觉得此处说的聚集译为:创建一个对象,属性可以为 ...
- Java核心技术卷一基础知识-第12章-泛型程序设计-读书笔记
第12章 泛型程序设计 本章内容: * 为什么要使用泛型程序设计 * 定义简单泛型类 * 泛型方法 * 类型变量的限定 * 泛型代码和虚拟机 * 约束与局限性 * 泛型类型的继承规则 * 通配符类型 ...
- Java核心技术-泛型程序设计
使用泛型机制编写的代码要比那些杂乱地使用Object变量,然后再进行强制类型转换的代码具有更好的安全性和可读性. 泛型对于集合类尤其有用 1 为什么要使用泛型程序设计 泛型程序设计意味着编写的代码可以 ...
- 《Java核心技术(卷1)》笔记:第8章 泛型程序设计
(P 327)"菱形"语法: ArrayList<String> files = new ArrayList<>(); // Java 9 扩展了菱形语法的 ...
随机推荐
- Spring知识点详解
1.Spring 概述 1.1.Spring 的概念和特点 Spring 是一个轻量级的控制反转(IoC)和面向切面(AOP)的开源容器框架,它是由 Rod Johnson(音乐学博士)所创建,其核心 ...
- Airbnb的动态kubernetes集群扩缩容
Airbnb的动态kubernetes集群扩缩容 本文介绍了Airbnb的集群扩缩容的演化历史,以及当前是如何通过Cluster Autoscaler 实现自定义扩展器的.最重要的经验就是Airbnb ...
- idea引入fastjson的jar包:ClassNotFound
idea 手动添加fastjson的jar包时,既在项目依赖里添加了,又在WEB-INF下的lib库里添加了 但是启动后就是加载不到,报错:ClassNotFound 尝试了好久,也参考了网上的许多建 ...
- 【C语言】超详讲解☀️指针是个什么针?(一次性搞定指针问题)
目录 前言 一. 什么是指针? 引例 计算机是怎么对内存单元编号的呢? 内存空间的地址如何得到 想存地址怎么办? 本质目的不是为了存地址 二.指针和指针类型 为什么有不同类型的指针 1.指针的解引 ...
- vue2升级vue3指南(二)—— 语法warning&error篇
本文总结了vue2升级vue3可能会遇到的语法警告和错误,如果想知道怎样升级,可以查看我的上一篇文章:vue2升级vue3指南(一)-- 环境准备和构建篇 Warning 1.deep /deep/和 ...
- 为你的网站加上live2d的动态小挂件,博君一晒
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_122 喜欢二次元的朋友一定对大名鼎鼎的live2d技术并不陌生,live2D是一种应用于电子游戏的绘图渲染技术,技术由日本Cybe ...
- 分布式二级缓存组件实战(Redis+Caffeine实现)
前言 在生产中已有实践,本组件仅做个人学习交流分享使用.github:https://github.com/axinSoochow/redis-caffeine-cache-starter 个人水平有 ...
- 后端编写Swagger接口管理文档
Swagger接口管理文档 访问接口文档的网页:http://localhost:8080/swagger-ui/index.html 导入依赖 <dependency> <grou ...
- .NET 扩展 官方 Logger 实现将日志保存到本地文件
.NET 项目默认情况下 日志是使用的 ILogger 接口,默认提供一下四种日志记录程序: 控制台 调试 EventSource EventLog 这四种记录程序都是默认包含在 .NET 运行时库中 ...
- 个人学习记录-Cpp基础-成员初始化列表
Translator Translator 参考链接: https://blog.csdn.net/XIONGXING_xx/article/details/115553291http ...