Java基础语法<十二> 泛型程序设计

1 意义

泛型程序设计意味着编写的代码可以被很多不同类型的对象所重用

常见应用 : ArrayList

2 K T V E ? object等的含义

类型变量使用大写形式

E – Element (在集合中使用,因为集合中存放的是元素)

T – Type(Java 类)(需要时还可以用临近的字母U和S)表示任意类型  S、U、V – 2nd、3rd、4th types

K – Key(键)

V – Value(值)

N – Number(数值类型)

? – 表示不确定的java类型(无限制通配符类型)

Object – 是所有类的根类,任何类的对象都可以设置给该Object引用变量,使用的时候可能需要类型强制转换,但是用使用了泛型T、E等这些标识符后,在实际用之前类型就已经确定了,不需要再进行类型强制转换。

3 泛型方法

public static <T> T getXXX(){

}

类型变量放在修饰符的后面,返回类型的前面

变量类型的限定

<T extends Comparable> T

一个类型变量或通配符可以有多个限定

T extends Comparable & Serializable

限定类型用&分隔,逗号用来分隔类型变量

在Java的继承中,可以根据需要拥有的多个接口超类型,但限定中至多有一个类,如果用一个类作为限定,它必须是限定列表中的第一个。

4 泛型代码和虚拟机

Java中的泛型基本上都是在编译器这个层次来实现的。

生成的Java字节代码中是不包含泛型中的类型信息的。

使用泛型的时候加上的类型参数,会被编译器在编译的时候去掉。 其实编译器通过Code sharing方式为每个泛型类型创建唯一的字节码表示,并且将该泛型类型的实例都映射到这个唯一的字节码表示上。将多种泛型类形实例映射到唯一的字节码表示是通过类型擦除(type erasue)实现的。

无论何时定义一个泛型类型,都自动提供一个相应的原始类型(raw type)。原始类型的名字就是删除类型参数后的泛型类型名。擦除(erased)类型变量,并替换为限定类型(无限定的变量用Object)

4.1 类型擦除

类型擦除指的是通过类型参数合并,将泛型类型实例关联到同一份字节码上。编译器只为泛型类型生成一份字节码,并将其实例关联到这份字节码上。类型擦除的关键在于从泛型类型中清除类型参数的相关信息,并且再必要的时候添加类型检查和类型转换的方法。 类型擦除可以简单的理解为将泛型java代码转换为普通java代码,只不过编译器更直接点,将泛型java代码直接转换成普通java字节码。

类型擦除的主要过程如下:

1.将所有的泛型参数用其最左边界(最顶级的父类型)类型替换。

2.移除所有的类型参数。

PS:

1.虚拟机中没有泛型,只有普通类和普通方法,所有泛型类的类型参数在编译时都会被擦除,泛型类并没有自己独有的Class类对象。比如并不存在List<String>.class或是List<Integer>.class,而只有List.class。

2.创建泛型对象时请指明类型,让编译器尽早的做参数检查(Effective Java,第23条:请不要在新代码中使用原生态类型

3.不要忽略编译器的警告信息,那意味着潜在的ClassCastException等着你。

4.静态变量是被泛型类的所有实例所共享的。对于声明为MyClass<T>的类,访问其中的静态变量的方法仍然是 MyClass.myStaticVar。不管是通过new MyClass<String>还是new MyClass<Integer>创建的对象,都是共享一个静态变量。

5.泛型的类型参数不能用在Java异常处理的catch语句中。因为异常处理是由JVM在运行时刻来进行的。由于类型信息被擦除,JVM是无法区分两个异常类型MyException<String>和MyException<Integer>的。对于JVM来说,它们都是 MyException类型的。也就无法执行与异常对应的catch语句。

5 泛型转换

Java虚拟机中没有泛型,只有普通的类和方法

所有的类型参数都用它们的限定类型替换

桥方法被合成来保持多态

为保持类型安全性,必要时插入强制类型转换

6 约束与局限性

  • 不能用基本类型实例化类型参数
  • 运行时类型查询只适用于原始类型
  • 不能创建参数化类型的数组
  • Varargs警告
  • 不能实例化类型变量
  • 泛型类的静态上下文中类型变量无效
  • 不能抛出或捕获泛型类的实例
  • 注意擦除后的冲突

7 通配符类型

7.1 <? extends T>

表示类型的上界,表示参数化类型的可能是T 或是 T的子类

7.2 <? super T >

表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object

带有超类型限定的通配符可以向泛型对象写入,带有子类型限定的通配符可以从泛型对象读取。

7.3 无限定通配符 <?>

ps:

如果要从集合中读取类型T的数据,并且不能写入,可以使用 ? extends 通配符;(Producer Extends)

如果要从集合中写入类型T的数据,并且不需要读取,可以使用 ? super 通配符;(Consumer Super)

如果既要存又要取,那么就不要使用任何通配符。

时间: 2024-10-25 15:20:35

Java基础语法<十二> 泛型程序设计的相关文章

Java基础语法(二)

目录 Java基础语法(二) 一.强类型语言 二.数据类型分类 1.基本数据类型 2.引用数据类型 三.基本类型转换 自动类型转换 强制类型转换 四.表达式类型的自动提升 Java基础语法(二) 承接上篇,谈到不同变量装载着不同数据类型的数据,那么Java支持的数据类型有哪些呢,本篇做一点小小的探究. 一.强类型语言 Java就是一种强类型的语言,包含着以下含义: 所有的变量必须在声明之后才能使用,不能用的不明不白或者用得很随意. 指定类型的变量只能结束类型与之匹配的值,很好理解,种瓜得瓜,种豆

Java基础语法(二)——数据类型扩展与运算符详解

一.前言 ? 上文我们讲解了有关java编程基础语法的变量与关键字的知识点,本文将主要对java基础语法中的运算符进行讲解. ? 在讲解语法之前我们先来讲一下真正的开发环境. 二.Java集成开发环境 2.1eclipse的使用方法 ? 之前我们在体验java编程或者写小的demo的时候,都是命名一个.java的源文件,在dos界面中编译和运行,但是这样给人的感觉并不友好,为了解决这一问题,一些大佬便开发了与各种语言对应的集成开发环境,其中包含文本编辑处理,自动编译,简化运行,随时进行代码调试.

java基础知识十二

第十二章 异常 异常(Exception):又称为例外,是程序在运行过程中发生的非正常事件,其发生会影响程序的正常执行.Exception是程序级错误,可由程序本身处理:Error是系统级错误,程序可不用处理.Java异常类都必须继承Throwable类或其子类.用户通过继承自定义异常.常见异常:除数为零.负数开方.数组越界.I/O异常. 抛出的异常由catch捕获,未被捕获的异常逐层传播直到main.如果main也没有处理该异常,则操作系统会终止main执行. 处理异常时,也可以抛出新异常,也

java基础语法要点&lt;二&gt;(基于1.8)

目录: 注解(元数据) I/O 泛型 lambda表达式 其他主题 内存管理 注解(元数据) : 从jdk5 开始,java支持在源文件中嵌入补充信息,称为注释(annotation).注释不会改变程序的动作,也就不会改变程序的语义.但在开发和部署期间,各种工具可以使用这类信息.元数据(metadata)也用于表示这一特性. 设计注释的主要目的是用于其他的开发和部署工具,但是如果为注释指定为RUNTIME保留策略,那么任何程序在运行时都可以使用反射来查询注释.反射时能够在运行时获取类相关信息的特

java基础第十二篇之集合、增强for循环、迭代器和泛型

Collection接口中的常用方法: * 所有的子类子接口都是具有的 * 集合的方法:增删改查 * * public boolean add(E e);//添加元素 返回值表示是否添加成功 * public boolean remove(Object o);//删除元素,返回值表示是否删除成功 * 没有修改方法 * 查询元素的方法没有,但是 * public int size();//查询集合集合中元素的个数 * //其他方法: * public void clear();//清空集合 * p

java基础(十二章)

一.变量的作用域(有效的使用范围) 1.变量有2种 1.1成员变量(属性) 声明在类的里面,方法的外面 1.2 局部变量 声明在方法里面或for循环结构中 2.调用时的注意事项(初始值不同.作用域不同) 2.1 成员变量,有默认值 在当前类直接通过成员变量名调用:在其他类中,通过该类的对象名.属性(成员变量)名调用:成员变量名称在同一个类中是唯一的. 2.2 局部变量,没有默认值,必须先赋值再使用 局部变量,只能在当前的方法中使用,其他方法和其他类不能调用:在同一个方法中名称是唯一的,但多个方法

黑马程序员——Java基础语法(二)语法结构

-----------android培训.java培训.java学习型技术博客.期待与您交流!------------ Java 中的语法结构有四种 顺序结构:顾名思义,就是按照顺序执行语句 判断结构:if  switch 选择结构: 循环结构:for  while   do while 1. if 结构 if语句有三种结构. (1)if(条件表达式){执行语句;} (2)if(条件表达式){执行语句;} else{执行语句;} (3)if(条件表达式){执行语句;} else if(条件表达式

Java基础(十二)IO输入输出

一.IO 概述 1.IO 概念 IO:I 代表 Input 输入:O 代表 Output 输出. Java 中 IO 是以流为基础进行输入输出,所有的数据被串行化(保存)写入输出流,或者从输入流读入. 注:数据串行化指把对象的状态以特定的形式(比如 byte[])保存到流,通过流的方式写入. 2.IO 的作用 1.文本文件,通过特定方法能够把数据写到文件,也能够读取出文件中的内容. 2.把信息保存到磁盘文件中. 3.Java 操作文件 1.创建 File 对象方式 测试创建文件的三种方式: 1

Java基础语法&lt;十&gt; Jar文件

1 JAR文件 java归档文件,压缩的 jdk/bin jar工具制作jar文件 jar程序选项 1.1清单文件 每个Jar文件包含一个用于描述归档特征的清单文件 manifest 清单文件被命名为MANIFEST.MF,它位于JAR文件的一个特殊META-INF目录中.最小的符合标准的清单文件是很简单的: Manifest-Version:1.0 1.2可运行Jar文件 可以使用Jar命令中的e选项指定程序的入口,即通常需要在调用Java程序加载器时指定的类: jar cvfe XXX.ja