一、泛型概述

1、什么是泛型

  • 泛型就是标签,加了泛型,就相当于加了标签,这个容器就只能放这一类物品。

  • 把元素的类型设参数,这个类型参数叫做泛型。Collection<E>,List<E>,ArrayList<E> 这个<E>就是类型参数,即泛型。

  • 所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值及参数类型。这个类型参数将在使用时(例如, 继承或实现这个接口,用这个类型声明变量 、创建对象时)确定(即传入实 际的类型参数,也称为类型实参)。

  • JDK1.5时引入。

2、为什么用泛型

  • 存储时:编译时进行类型检查来保证,存放的都是类型一样的数据,更安全。
  • 获取时:获取的都是类型一样的数据,无序强转

3、在集合中使用泛型

  • ① 集合接口或集合类在jdk5.0时都修改为带泛型的结构。
  • ② 在实例化集合类时,可以指明具体的泛型类型。

  • ③ 指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法、构造器、属性等)使用到类的泛型的位置,都指定为实例化的泛型类型。

    比如:add(E e) --->实例化以后:add(Integer e)。

  • ④ 注意点:泛型的类型必须是类,不能是基本数据类型。需要用到基本数据类型的位置,拿包装类替换。

  • ⑤ 如果实例化时,没有指明泛型的类型。默认类型为java.lang.Object类型。

  • ⑥在JDK7中新特性:类型推断

    • List<String> list = new List<>();后面的泛型可以省略

二、自定义泛型结构

1、泛型类、接口

  • 自定义泛型类代码实现:核心思想就是把T当做一个某某类型的参数,只不过需要在尖括号标明
/**
* 自定义泛型类
*/
public class MyGeneric<T> {
String name;
int age;
T decs;//可以把他当做一个类来看,但是并不是类,而是参数 public MyGeneric() {
} //带参构造器
public MyGeneric(String name, int age, T decs) {
this.name = name;
this.age = age;
this.decs = decs;
} //get()方法
public T getDecs() {
return decs;
} //set()方法
public void setDecs(T decs) {
this.decs = decs;
} //toString()方法
@Override
public String toString() {
return "MyGeneric{" +
"name='" + name + '\'' +
", age=" + age +
", decs=" + decs +
'}';
}
}
  • 子类继承父类时,泛型的情况

    • 说明:子类是“富二代”,除了指定或保留父类的泛型,还可以增加自己的泛型。
    • 情况一:子类不保留父类的泛型
      • 父类没有类型,擦除,类型按照Object处理
      • 父类是具体类型
    • 情况二:子类保留父类的类型
      • 全部保留
      • 部分保留
    • 代码示例
class Father<T1, T2>{
} //子类不保留父类的泛型
//1)没有类型,擦除--->这时,子类不是泛型
class Son1 extends Father{//等价于class Son extends Father<Object,Object>{
} //2)具体类型--->这时,子类不是泛型
class son2 extends Father<Integer, String>{
} //子类保留父类的泛型
//1)全部保留
class Son3<T1, T2> extends Father<T1, T2>{
}
//2)部分保留
class Son4<T2> extends Father<Integer, T2>{
} //当然子类也可以加上自己的新的泛型类型

  • 注意点

    • 泛型类里的泛型是以参数的形式存在的。

    • 可以有多个参数:<T1,T2,T3>

    • 声明构造器时

      • 空参构造器和普通的一样 public MyGeneric() {}
      • 带参构造器体现在参数上 public MyGeneric(String name, int age, T decs) {
    • 泛型不同的引用不能相互赋值

      ArrayList<String> list1 = new ArrayList<>();
      ArrayList<Integer> list2 = new ArrayList<>(); list1 = list2;//这样是错误的!
    • 泛型如果不指定,就会被擦除,泛型对应的类型按照Object处理,但不等价于Object。

    • 在类/接口上声明的泛型,在本类或本接口中即代表某种类型,可以作为非静态 属性的类型、非静态方法的参数类型、非静态方法的返回值类型。但在静态方法中不能使用类的泛型。(因为,静态方法随着类的加载而加载,而泛型是在实例化的时候指定,晚于静态方法出生)

    • 异常类不能声明为泛型的。

    • 如果想在构造器中初始化一个T类型的数组,要写作:

      T[] t = (T[])new Object[capacity]

2、泛型方法

  • 理解

    • 在方法中出现了泛型的结构,就是泛型方法。
    • 泛型方法中的泛型参数与类的泛型参数没有关系。也就是说:泛型方法所属的类是不是泛型无所谓。
    • 可以声明为静态的,因为泛型参数是在调用方法时确定的,而不是来加载时。
  • 代码实现一个泛型方法
public static <E> List<E> copyFromArrayToList(E[] arr){
//这里的第一个<E>是为了不让编译器把E当做是一个我们自定义的类
ArrayList<E> list = new ArrayList<>(); for(E e : arr){
list.add(e);
} return list;
}

三、举例泛型类和泛型方法的使用场景

1、泛型类举例:

连接数据库时,操作数据库中的表的记录

  • DAO类:定义了数据库不同表的一些共性操作的类

    public class DAO<T> {}

  • CustomerDAO:定义了专门操作Customer表的类

    public class CustomerDAO extends DAO<Customer>{}

2、泛型方法举例

//泛型方法举例
/*
返回的东西是不确定的,比如
需求1:表中有多少条记录
需求2:获取工资最大值
*/
public <E> E getSomething(){
return null;
}

四、泛型在继承上的体现

  • 首先,我们知道在多态下,子类的对象可以赋给父类的引用。
  • 但是,在泛型情况下,不再存在子父类的关系。例如,String是Object的子类,但是List<String >并不是List<Object> 的子类。同理在方法参数中也一样适用。这样就导致一个问题,同一功能的方法要重载很多次。
  • 区别,类B是类A的子类,那么B<T>仍然是A<T>的子类。

五、通配符

1、通配符

通配符用 ?来表示,含义为:类A是类B的父类,G<A> G<B>并不存在什么关系,二者的共同父类是:G<?>。这样就不必重载那么多功能相同的方法了。

2、添加通配符后数据的写入何人读出

  • 写入:对于List<?>,不能向其中添加数据,只能添加null;
  • 读出:可以读取,读取出的数据为Object类型

3、有限制条件的通配符

  • 首先,通配符?可以的范围可以理解为: (无穷小,无穷大)
  • ? extends A的范围就可以理解为:小于等于,即(无穷小,A]
  • ? super A的范围就可以理解为:大于等于,即[A,无穷大)

Java(7)泛型的更多相关文章

  1. [改善Java代码]Java的泛型是类型擦除的

    泛型可以减少强制类型的转换,可规范集合的元素类型,还可以提高代码的安全性和可读性,正是因为有了这些优点,自从Java引入泛型之后,项目的编码规则上便多了一条,优先使用泛型. Java泛型(Generi ...

  2. Java 中泛型的全面解析(转)

    Java泛型(generics) 是JDK 5中引入的一个新特性,允许在定义类和接口的时候使用类型参数(type parameter).声明的类型参数在使用时用具体的类型来替换.泛型最主要的应用是在J ...

  3. Java中泛型 类型擦除

    转自:Java中泛型是类型擦除的 Java 泛型(Generic)的引入加强了参数类型的安全性,减少了类型的转换,但有一点需要注意:Java 的泛型在编译器有效,在运行期被删除,也就是说所有泛型参数类 ...

  4. Java 泛型 Java使用泛型的意义

    Java 泛型 Java使用泛型的意义 @author ixenos 直接意义 在编译时保证类型安全 根本意义 a) 类型安全问题源自可复用性代码的设计,泛型保证了类型安全的复用模板 b) 使用复用性 ...

  5. 跟着刚哥梳理java知识点——泛型(十三)

    一. 泛型概念的提出(为什么需要泛型)? 首先,我们看下下面这段简短的代码: public class GenericTest { public static void main(String[] a ...

  6. 【Java】泛型学习笔记

    参考书籍 <Java核心技术:卷1> 泛型, 先睹为快 先通过一个简单的例子说明下Java中泛型的用法: 泛型的基本形式类似于模板, 通过一个类型参数T, 你可以"私人定制&qu ...

  7. [转] Java 的泛型擦除和运行时泛型信息获取

    原文链接 https://my.oschina.net/lifany/blog/875769 前言 现在很多程序员都会在简历中写上精通 Java.但究竟怎样才算是精通 Java 呢?我觉得不仅要熟练掌 ...

  8. Java 容器 & 泛型:五、HashMap 和 TreeMap的自白

    Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket Java 容器的文章这次应该是最后一篇了:Java 容器 系列. 今天泥瓦匠聊下 Maps. 一.Ma ...

  9. 【译】9. Java反射——泛型

    原文地址:http://tutorials.jenkov.com/java-reflection/generics.html ===================================== ...

  10. Java“禁止”泛型数组

    Java“禁止”泛型数组 原文:https://blog.csdn.net/yi_Afly/article/details/52058708 1. 泛型定义泛型编程是一种通过参数化的方式将数据处理与数 ...

随机推荐

  1. php查看进程

      index.php <?php /** * Created by PhpStorm. * User: mac * Date: 2020/4/23 * Time: 21:57 */ echo ...

  2. Linux命令的执行

    为什么在提示符下命令可以被执行呢? 执行命令过程 输入命令后回车,提请shell程序找到键入命令所对应的可执行程序或代码,并由其分析后提交给内核分配资源将其运行起来 shell本身也是一个程序,只不过 ...

  3. Django采坑日志(django2.0)

    使用Mariadb时出现的问题 "Unknown system variable 'transaction_isolation'" 解决办法:修改django/db/backend ...

  4. App在后台运行时如何保存数据到sqlite数据库

    iOS程序进入后台后,是不允许读写任何文件和数据库(sqlite),但是允许读写NSUserDefault中的数据. 因此在后台时如果想存储数据,则可使用NSUserDefault(偏好设置)临时保存 ...

  5. 给大家分享一下java数据库操作步骤

    获取驱动程序Jar文件,并放置到项目的类路径中: 注册驱动器类: 获取数据库连接: 获取Statement对象来执行相关SQL操作: 关闭各种资源;

  6. STM32入门系列-存储器与寄存器介绍

    介绍两部分内容: 什么是存储器映射 什么是寄存器及寄存器映射 为了让大家对存储器与寄存器有一个更清楚的认识,并且为之后使用 C 语言来访问 STM32 寄存器内容打下基础.等明白了如何使用 C 语言封 ...

  7. centos8 curl: (35) error:141A318A:SSL routines:tls_process_ske_dhe:dh key too small

    centos8操作系统,curl -k https:/www.xxx.com 报错  curl: (35) error:141A318A:SSL routines:tls_process_ske_dh ...

  8. [Luogu P3119] [USACO15JAN]草鉴定Grass Cownoisseur (缩点+图上DP)

    题面 传送门:https://www.luogu.org/problemnew/show/P3119 Solution 这题显然要先把缩点做了. 然后我们就可以考虑如何处理走反向边的问题. 像我这样的 ...

  9. JS中使用for-each遍历数组

    1 let array = [1, 3, 6, 8, 9, 0, 5]; 2 /* 3 index是数组索引 4 value代表数组的值 5 arr是指整个数组 6 */ 7 array.forEac ...

  10. CF1413C Perform Easily 题解

    毒瘤C题,考场卡我1个小时 首先,这道题难点在哪里?它的最大值与最小值都是浮动的. 怎么办?把最小/最大值固定! 以把最小值固定为例,我们枚举每个音符,并枚举它使用哪条琴弦,将它此时的位置强制其作为最 ...