这是我参与8月更文挑战的第1天,活动详情查看:8月更文挑战
废话:迄今为止,工作也一年有余了,一直没有对知识体系有一个系统的总结。就让我从这个8月开始吧。我只是Android路上的一个小菜鸡,其实呢,这篇文章之前在其他博客发过一次,希望大家帮忙指正错误的地方。 The nonsense is over!
为什么使用泛型
在介绍为什么使用泛型前我们需要了解什么是泛型?
泛型的定义主要有以下两种:
不论使用哪个定义,泛型的参数在真正使用泛型时都必须作出指明。
一些强类型程序语言支持泛型,其主要目的是加强类型安全及减少类转换的次数,但一些支持泛型的程序语言只能达到部分目的。(摘自百度百科)
正文:当我们将一个对象放入集合中,集合并不会记住此对象的类型,当再次从集合中取出此对象时,该对象的编译类型变成了Object类型,但其运行时类型,依然为其本身类型。 因此,在取出集合元素时,需要人为的进行强制转换到具体的目标类型,且容易出java.lang.ClassCastException。
所以泛型的好处就是:
- 适用于多种数据类型执行相同的代码
- 在使用是就制定泛型中的类型,不需要强制转换
泛型类与泛型接口的定义
- 泛型,即“参数化类型”。提到参数,我们熟悉的就是定义方法时有形参然后调用此方法时传递参数。那么参数化类型是什么?
- 顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(类型形参),然后在使用/调用时传入具体的类型(类型实参)。
什么是泛型类
如果之前有看过我写的单例模式文章的同学,应该对这个类不陌生。"我的理解为在声明类名出声明出泛型的类便是泛型类"
import java.util.Objects;
/**
* 泛型类
* 泛型类是允许有多个类型变量的,例如Singleton<T,V>
* @param <T>
*/
public abstract class Singleton<T>{
private T instance;
public abstract T create();
public final T getInstance(){
if(Objects.isNull(instance)){
synchronized (this){
if(Objects.isNull(instance)) instance = create();
}
}
return instance;
}
}
什么是泛型接口
泛型接口,在接口名处,声明出泛型类型。
public interface Generator<T> {
public T next();
}
泛型方法辨析
泛型方法,是在调用方法时指明泛型的具体类型,泛型方法可以在地方和场景中使用,包括普通类和泛型类。
public class GenertorMethod<T> {
private T key;
/**
* 泛型方法是独立的,没必要声明在泛型类和泛型方法中
*
* @param a
* @param <T>
* @return
*/
public <T> T genericMethod(T...a){
return a[a.length/2];
}
/**
* 虽然返回值是泛型,但他不是泛型方法
* 若此类不是泛型类,编译报错。
* @return
*/
public T commonMethod(){
return key;
}
/**
* @param str 在定义方法的时候,只需将最后一个形参后加上"…",就可以表示该形参可以接收多个参数值,多个参数值被当成数组传入
* @return
*/
public String demo_1(String...str){
for (String s : str) {
if(s == "ok"){
return s;
}
}
return null;
}
}
限定类型变量
<T extend Comparable>有时需要对类型变了加以约束,比如比较大小。- 同时extends左右都允许有多个,如 T,V extends Comparable & Serializable
- 注意限定类型中,只允许有一个类,而且如果有类,这个类必须是限定列表的第一个。这种类的限定既可以用在泛型方法上也可以用在泛型类上。
/**
* @param a
* @param b
* @param <T> T必须为Comparable的派生类,或者实现接口, 但是类只可以有一个,因为Java单继承
* extends 左右俩边可以有多个参数
* @return
*/
public static <T extends ArrayList & Comparable & Serializable> T min(T a, T b){
if (a.compareTo (b) > 0)return b;else return a;
}
泛型中的约束和布局
- 不能用基本类型实例化参数类型 不被允许的使用
GenertorMethod<int> genertorMethod = new GenertorMethod();
正确的使用
GenertorMethod<Integer> genertorMethod = new GenertorMethod();
- 泛型类的静态上下文中类型变量失效,静态域或者方法里不能引用类型变量,静态方法本身是泛型方法可以。 不被允许的使用
private static T getInstances(){return null;}
正确的使用
private static <T> T getT(){return null;}
- 不能创建参数化类型的数组,其实主要是为了避免数组里出现类型不一致的元素** 不被允许的使用
GenertorMethod<Integer>[] genertorMethods = new GenertorMethod<Integer>[10];
泛型类型的继承规则
//请问arrayList_1和arrayList_2是继承关系吗?
//答案:不是,他们之间没有什么关系
ArrayList<ArrayList> arrayList_1 = new ArrayList();
ArrayList<AbstractList> arrayList_2 = new ArrayList();
通配符类型
? extends X 表示类型的上界,类型参数是X的子类
? super X 表示类型的下界,类型参数是X的超类