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)

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

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

  1. java基础语法(二)--单列模式

    java基础语法(二)--单列模式 /** * 功能:单列模式 * @author Administrator * */ public class SingletonTest { public sta ...

  2. 03:Java基础语法(二)

    Java基础语法 Java运算符 算术运算符 运算符是一种特殊的符号,用以表示数据的运算.赋值和比较等.1.操作数:参与运算的数据 称为操作数.2.表达式:运算符和操作数的整体 称为表达式.单独的一个 ...

  3. java基础语法要点<二>(基于1.8)

    注解(元数据) 从jdk5 开始,java支持在源文件中嵌入补充信息,称为注释(annotation).注释不会改变程序的动作,也就不会改变程序的语义.但在开发和部署期间,各种工具可以使用这类信息.元 ...

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

    Collection接口中的常用方法: * 所有的子类子接口都是具有的 * 集合的方法:增删改查 * * public boolean add(E e);//添加元素 返回值表示是否添加成功 * pu ...

  5. Java基础加强总结(二)——泛型

    一.体验泛型 JDK1.5之前的集合类中存在的问题——可以往集合中加入任意类型的对象,例如下面代码: package cn.gacl.generic.summary; import java.util ...

  6. Java基础(十二):包(package)

    一.Java 包(package): 为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间.包的作用: 1.把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用. 2.如同文件夹 ...

  7. Java基础之十五 泛型

    第十五章 泛型 一般的类和方法,只能使用具体的类型:要么是基本类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大. 在面对对象编程语言中,多态算是一种泛化机 ...

  8. 夯实Java基础(十二)——异常处理

    1.异常处理概述 在Java程序执行过程中, 总是会发生不被期望的事件, 阻止程序按照程序员预期正常运行, 这就是Java程序出现的异常. 异常处理是基于面向对象的一种运行错误处理机制,通过对异常问题 ...

  9. java基础(十二章)

    一.变量的作用域(有效的使用范围) 1.变量有2种 1.1成员变量(属性) 声明在类的里面,方法的外面 1.2 局部变量 声明在方法里面或for循环结构中 2.调用时的注意事项(初始值不同.作用域不同 ...

随机推荐

  1. python 第五弹

    *:first-child { margin-top: 0 !important; } .markdown-body>*:last-child { margin-bottom: 0 !impor ...

  2. Scrapy中使用Django的Model访问数据库

    Scrapy中使用Django的Model进行数据库访问 当已存在Django项目的时候,直接引入Django的Model来使用比较简单 # 使用以下语句添加Django项目的目录到path impo ...

  3. JavaFx TableView疑难详解

    TableView是个十分有用的控件,适应性和灵活性非常强,可以对它进行任意的修改,比如界面样式.功能.本文将从一步步提问的方式讲解TableView 创建已知列的TableView 已知列的表格的创 ...

  4. 警告: [SetContextPropertiesRule]{Context} Setting property 'source' to 'org.eclipse.jst.jee.server:JsonBlog' did not find a matching property.

    这个问题困扰很久了,逛了很多论坛,终于得以解决 我的控制台错误如下: 五月 , :: 下午 org.apache.catalina.startup.VersionLoggerListener log ...

  5. Struts+jdbc+分页 实例

    根据项目里分页实例,带有注解. package org.tarena.netctoss.dao.impl; import java.sql.Connection; import java.sql.Pr ...

  6. MATLAB仿真中连续和离散的控制器有何区别?

    matlab系统同时提供连续和离散的控制器和对象的目的是:在降低用户使用复杂程度的同时提高仿真精度.仿真速度和应用的广泛性. 仿真步长和求解精度的概念对于理解这个问题至关重要. 首先是步长,步长和求解 ...

  7. matplotlib.pyplot.hist

    **n, bins, patches = plt.hist(datasets, bins, normed=False, facecolor=None, alpha=None)** ## 函数说明 用于 ...

  8. 理解Java中的抽象

    在计算机科学中,抽象是一种过程,在这个过程中,数据和程序定义的形式与代表的内涵语言相似,同时隐藏了实现细节. 抽象:一个概念或者想法不和任何特定的具体实例绑死. 目录 什么是抽象 抽象的形式 如何在J ...

  9. python 标准库 -- pickle & cPickle

    pickle & cPickle pickle 和 cPickle 除了导入名称不一样之外, 使用方法, 均一样. pickle 导入 import pickle cPickle 导入 imp ...

  10. Mac 性能测试环境搭建——理论篇

    此篇为博主原创内容,若转载请写明出处,谢谢! 前言在搭建之初,我们要思考的2个点:1.性能怎么测试?2.性能的测试环境如何搭建(该如何去做)?1.什么是性能?    个人理解为:合理的架构.低耦合.高 ...