浅谈java泛型
Posted Al_tair
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈java泛型相关的知识,希望对你有一定的参考价值。
常用集合类
大家好呀!我是小笙!我学习了韩顺平老师的类和对象的知识,收获颇丰!现在来和大家分享笔记!
基本介绍
Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
泛型特点
-
可以使用任意字母A-Z T 是 type的缩写,比较常用
// 自定义泛型 class Template<E> E filed; @Override public String toString() return "Template" + "filed=" + filed + ''; public E method() return filed; public Template(E filed) this.filed = filed;
-
只能指代引用类型的数据
-
在给泛型指定具体类型后,可以传入该类型或者其子类类型
public class Generic02 public static void main(String[] args) C<A> C = new C<A>(new A()); C<A> C2 = new C<A>(new B()); class A class B extends A class C<E> E c; public C(E c) this.c = c;
-
泛型的使用形式
ArrayList<Integer> arrayList = new ArrayList<Integer>(); ArrayList<Integer> arrayList2 = new ArrayList<>(); // 推荐 ArrayList arrayList = new ArrayList(); // 默认泛型为Object
分析泛型编译后的文件
java里面的泛型只存在于源代码里面,一旦经过编译之后,所有的泛型都会被擦除掉,全部被替换为原来的裸类型,并在对元素进行访问和修改的时候,才会加上强制类型转换。
// (所谓的裸类型指的是,ArrayList<Integer>() 他的裸类型就是ArrayList())
public class Test
public static void main(String[] args)
ArrayList<String> sList = new ArrayList<String>();
ArrayList<Integer> iList = new ArrayList<Integer>();
// getClass()方法 表示此对象的运行时类的Class对象
System.out.println(sList.getClass() == iList.getClass()); // true
// 代码
public class Generic02
public static void main(String[] args)
C<A> C = new C<A>(new A());
C<A> C2 = new C<A>(new B());
A a = C.c;
class A
class B extends A
class C<E>
E c ;
E[] e;
public C(E c)
this.c = c;
// 反编译代码 IDEA 选中代码 -> View -> Show Bytecode 或者 cmd 输入 javap -c XXX.class
// 我删除了一些不必要的代码
public class com/Al_tair/generic_/Generic02
// 省略始化Generic02类
public static main([Ljava/lang/String;)V
L0 // C<A> C = new C<A>(new A());
LINENUMBER 9 L0
NEW com/Al_tair/generic_/C
DUP
NEW com/Al_tair/generic_/A
DUP
INVOKESPECIAL com/Al_tair/generic_/A.<init> ()V
// Ljava/lang/Object; (L开头 内容是对象 ;结尾 ) 传入是Object对象
// 原本默认传进去就是Object类的对象,使用的时候使用自动强转换成对应传入的类型(现象如下)
INVOKESPECIAL com/Al_tair/generic_/C.<init> (Ljava/lang/Object;)V
ASTORE 1
L1 // C<A> C2 = new C<A>(new B());
LINENUMBER 10 L1
NEW com/Al_tair/generic_/C
DUP
NEW com/Al_tair/generic_/B
DUP
INVOKESPECIAL com/Al_tair/generic_/B.<init> ()V
INVOKESPECIAL com/Al_tair/generic_/C.<init> (Ljava/lang/Object;)V
ASTORE 2
L2
LINENUMBER 11 L2
RETURN
GETFIELD com/Al_tair/generic_/C.c : Ljava/lang/Object;
// 此处有一个checkcast指令,checkcast 用于检查类型强制转换是否可以进行,也就是泛型在获取值的时候进行了强制类型转换。
CHECKCAST com/Al_tair/generic_/A
L3
......
类型擦除的缺点
1.使用类型擦除直接导致了对于原始的数据类型无法支持,比如int,long这种,因为java不支持Object类型和基本数据类型之间的强制类型转换,也就是说一旦类型擦除之后,就没法在进行 类型转换了。也正是这样,现在的泛型都是不支持原始类型的,比如ArrayList,而不能使用ArrayList。
2.运行期间无法获得泛型类型信息。因为泛型都被擦除了,都被替换成了裸类型。这样就导致了下面的程序都会报错,比如无法使用泛型来创建对象,或者数组。
自定义泛型
自定义泛型类
基本语法
class 类名<泛型>
注意细节
-
泛型类的类型是在创建对象时确定的(因为创建对象时,需要指定确定的类型)所以在类加载就创建的成员无法使用泛型
-
普通成员可以使用泛型(属性和方法)但是成员变量不能赋值
-
静态方法中不能使用类的泛型
-
使用泛型的数组不能直接初始化 不能初始化的原因
// E[] e = new E[3]; 报错
-
自定义泛型接口
基本语法
interface 接口名<泛型>
注意细节
- 静态成员中不能使用类的泛型
- 泛型接口的类型是在实现接口的时候确定的
- 没有指定类型,则默认为Object类型
自定义方法
基本语法
// 一般参数列表和泛型对应
修饰符<泛型>返回类型 方法名(参数列表)
// 以下非泛型方法,而是使用了泛型
public void XXX(E e)
注意细节
- 泛型方法可以放在普通类或者泛型类中
- 方法在使用之前,类型必须确定
泛型的继承和同配符
- 泛型不具有继承性
- <?> : 支持任意类型
- <? extends A> :支持A 类以及A类的子类,规定了泛型的上限
- <> super A> ;支持A类以及A类的父类,规定了泛型的下限
相关面试题
什么是泛型?泛型的作用?
- Java 泛型(Generics)是 JDK 5 中引入的一个新特性。
- 使用泛型参数,可以增强代码的可读性以及稳定性。编译器可以对泛型参数进行检测,并且通过泛型参数可以指定传入的对象类型。比如
ArrayList<Persion> persons = new ArrayList<String>()
这行代码就指明了该ArrayList
对象只能传入Persion
对象,如果传入其他类型的对象就会报错。 - 可以用于构建泛型集合。原生
List
返回类型是Object
,需要手动转换类型才能使用,使用泛型后编译器自动转换。
以上是关于浅谈java泛型的主要内容,如果未能解决你的问题,请参考以下文章