title: Java泛型详解
date: 2021-03-27 11:12:58
tags: 学习一下泛型吧!铁汁!
一篇博文
https://blog.csdn.net/s10461/article/details/53941091?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161726856216780262572785%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=161726856216780262572785&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-1-53941091.first_rank_v2_pc_rank_v29&utm_term=java%E6%B3%9B%E5%9E%8B
泛型的概念
泛型,即“参数化类型”,顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。
也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别称为泛型类、泛型接口、泛型方法。
为什么要使用泛型?
List arrayList = new ArrayList();
arrayList.add("aaaa");
arrayList.add(100);
for(int i = 0; i< arrayList.size();i++){
String item = (String)arrayList.get(i);
Log.d("泛型测试","item = " + item);
}
ArrayList可以存放任意类型,例子中添加了一个String类型,再使用时都以String的方式使用,因此程序崩溃了。为了解决类似的问题(就是在编译阶段就可以解决),泛型应运而生。
List<String> arrayList = new ArrayList<String>();
...
//arrayList.add(100); 在编译阶段,编译器就会报错
这样在编译阶段,程序就会报错!
为什么要使用泛型方法呢?因为泛型类要在实例化的时候就指明类型,如果想换一种类型,就不得不重新new一次,可能不够灵活;而泛型方法可以在调用的时候就指明类型,更加灵活。
怎么使用泛型?
泛型有三种使用方式,分别为:泛型类、泛型接口、泛型方法。
具体看:https://blog.csdn.net/s10461/article/details/53941091?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161726856216780262572785%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=161726856216780262572785&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-1-53941091.first_rank_v2_pc_rank_v29&utm_term=java%E6%B3%9B%E5%9E%8B
泛型的注意点
1.泛型只在编译阶段有效。
在编译之后,程序会采取去泛型化的措施。泛型类型在逻辑上可以看成是多个不同的类型,实际上都是相同的基本类型
2.泛型的类型参数只能是类类型,不能是简单类型。
3.不能对确切的泛型类型使用instanceof操作。如下面的操作是非法的,编译时会出错。
Coffee<Breve> coffee = new Coffee<>();
//if语句括号里面的直接在编译阶段就报错了
if (coffee instanceof Coffee<Breve>){
System.out.println("true");
}
4.同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。
5.’?‘泛型通配符是类型实参,而不是类型形参。什么意思?就是此处的?和Number、String、Integer一样都是一种实际的类型,可以把?看成所有类型的父类,是一种真实的类型。
6.泛型类,是在实例化类的时候指明泛型的具体类型;泛型方法,是在调用方法的时候指明泛型的具体类型。
7.静态方法无法访问类上定义的泛型;如果静态方法操作的引用数据类型不确定的时候,必须将泛型定义在方法上。如果静态方法要使用泛型的话,必须将静态方法也定义成泛型方法。
8.为泛型添加上边界,即传入的类型实参必须是指定类型的子类型。
9.泛型的上下边界添加,必须与泛型的声明在一起。
10.不能创建一个确切的类型的数组,而使用通配符创建泛型数组是可以的。
11.数组的类型不可以是类型变量,除非是采用通配符的方式。因为对于通配符的方式,最后取出的数据是要做显式的类型转化
一个疑问
ArrayList<?extends Object> al = new ArrayList();
al.add(“aa”); //错
//因为集合具体对象中既可存储String,也可以存储Object的其他子类,所以添加具体的类型对象不合适,类型检查会出现安全问题。 ?extends Object 代表Object的子类型不确定,怎么能添加具体类型的对象呢?
public static void method(ArrayList<? extends Object> al) {
al.add(“abc”); //错
//只能对al集合中的元素调用Object类中的方法,具体子类型的方法都不能用,因为子类型不确定。
什么意思?