Java基础 -- 泛型

Java基础 -- 泛型

1. 为什么引入泛型?

集合的使用过程中存在两个问题:

  • 将元素丢进集合中,集合不会记得元素类型,所以在取出时要进行强制类型转换,一方面增加编程复杂度,另一方面可能会造成异常;这时造成的异常在运行时报异常,我们期望在编译阶段就能发现问题(编译时类型检查);

  • 集合对元素类型没有限制,可能引发问题;比如定义了一个只能存放Dog对象的集合,此时向集合中扔入一个Cat对象,引发异常。

为了解决上述两个问题,引入了泛型。

2. 什么是泛型?

泛型,也叫做参数化类型,实际上就是在创建集合时候就指定集合的类型。

那么泛型是怎么来指定集合类型呢?

集合类型<数据类型> 集合名 = new 集合类型<数据类型> ();

【注】<>中的可以看作一个参数

3. 如何使用泛型?

泛型主要有三种使用方式:泛型类,泛型方法,泛型接口

  • 泛型类:泛型用于定义类

泛型类定义格式如下:
修饰符 class 类名<代表泛型的变量> { ... }

public class GenericsClassDemo<T> {
  ...
}

【注】定义类GenericsClassDemo,类的类型此时为T,T相当于一个参数,代表未知,类的具体类型在使用时候(也就是创建对象时候)才知道。
泛型在定义的时候不具体,使用的时候才变得具体。在使用的时候确定泛型的具体数据类型。即:在创建对象的时候确定泛型

  • 泛型方法:调用方法时知名泛型具体类型

泛型方法定义格式如下:

修饰符 <代表泛型的变量> 返回值类型 方法名(参数){... }

   public <T> T genercMethod(T t){
   //方法体
   }

【注】定义方法genercMethod(),返回值类型为T,调用方法时候才能知道具体类型,包括返回值类型和参数类型。

  • 泛型接口:泛型用于定义接口

泛型接口定义格式如下:

修饰符 interface接口名<代表泛型的变量> { }

public interface GenericsInteface<T> {
 public abstract void add(T t); 
}

【注】定义接口GenericsInterface,接口类型为T,接口类型确定有两种情况:(1)定义类时确定接口类型;(2)创建对象时确定接口类型

4. 类型通配符

5. 类型擦除

要想理解什么是类型擦除,需要从以下两个问题入手:

Q1: 我们编写的.java文件是如何成为机器语言执行的呢?

A : 概括来说,由程序员编写的.java文件使用javac编译生成.class文件,字节码上JVM运行,在JVM中内部使用java解释执行生成特定平台的机器码。

Q2: Java是伪泛型,如何理解伪泛型呢?

A : 对于JVM来说,普通类和泛型类没有区别,也就是说,泛型这个概念只存在于编译阶段,编译成字节码文件上JVM运行就看不出来泛型类和普通类的区别了。

也就是说,**Java 在编译期间,所有的泛型信息都会被擦掉 **(Java编译器生成的字节码是不包涵泛型信息的)

由此可以得出类型擦除的定义

泛型信息只存在于代码编译阶段,进入JVM之前,与泛型相关的信息会被擦除,这就是类型擦除

参考资料

https://zhuanlan.zhihu.com/p/382239048
https://blog.csdn.net/briblue/article/details/76736356
https://zhuanlan.zhihu.com/p/346486993

posted @ 2022-06-11 21:06  Claire_2099  阅读(36)  评论(0编辑  收藏  举报