文章目录
- 泛型
- 一、泛型的好处
- 二、自定义泛型
- 1.自定义泛型类
- 2.自定义泛型接口
- 2.自定义泛型方法
- 三、泛型的继承和通配符
泛型
字面理解:泛(广泛,宽泛)型(类型)
泛型,又称参数化类型,泛型的本质是把数据类型进行了参数化,即需要使用不同的类型的时候,通过把泛型作为形式参数,来指定不同的实际使用时的类型。
一、泛型的好处
1、泛型中的类型是在使用时指定的,不需要进行强制类型转换,即类型安全,编译器会自己检查使用的类型。
2、减少了类型转换的次数,提高程序执行效率。
3、使用方便,在类声明或者实例化的时候,只需要指定需要使用的类型即可。
4、适用于多种数据类型执行相同的代码,增强了代码复用性。
二、自定义泛型
1.自定义泛型类
class 类名 < T, R, M > { }
- 类名后接 泛型,该类就称为自定义泛型类
- T, R, M 为泛型的标识符, 一般是单个大写字母都行
- 泛型标识符可以有多个
- 泛型类的普通成员(属性、方法)可以使用泛型
- 泛型类使用泛型的数组,不能初始化,因为数组在创建时不能确定泛型的具体类型,就无法在内存中分配空间
- 泛型类的 静态方法 和 静态属性 不能使用泛型类的泛型
代码如下(示例):
class Animal<T, R, M> {
//属性使用泛型
R r;
M m;
T t;
//数组使用泛型
T[] array;
//构造器使用泛型
public Animal(R r, M m, T t) {
this.r = r;
this.m = m;
this.t = t;
}
//静态方法和属性不能使用泛型:
//因为静态是和类相关的,在类加载时,对象还没有创建
//所以,如果静态方法和静态属性使用了泛型,JVM就无法完成初始化
// static R r2;//错
// public static void m1(M m) {}//错
//方法使用泛型,返回类型可以使用泛型
public R getR() {
return r;
}
public M getM() {
return m;
}
public T getT() {
return t;
}
}
2.自定义泛型接口
interface 接口名 < K,T > { }
- 接口名后接 泛型,该接口就称为自定义泛型接口
- 泛型接口的 属性 不能使用泛型(因为接口的属性默认为静态的)
- 泛型接口的 方法 可以使用泛型
- 泛型接口的使用的类型,在该接口被继承或实现的时候指定
- 泛型接口的类型在使用时不指定默认为Object类型
代码如下(示例):
interface MySet<K, T> {
//泛型接口的 属性 不能使用泛型
//K k;//错
//T t;//错
//泛型接口的 方法 可以使用泛型
K a(K k);
T b(T t);
}
//泛型接口的使用的类型,在该接口被继承或实现的时候指定
interface MySet02 extends MySet<Integer, Double>{
//说明:Integer即 K 的实际使用类型
// Double即 T 的实际使用类型
}
class A implements MySet02<Integer, Double>{
public Integer a(Integer k){
return null;
}
public Double b(Double t){
return null;
}
}
//泛型接口的类型在使用时不指定默认为Object类型
class A implements MySet{
//等价于 class A implements MySet02<Object,Object>
public Object a(Object k){
return null;
}
public Object b(Object t){
return null;
}
}
2.自定义泛型方法
修饰符 < E > 返回值类型 方法名(参数列表) { }
- 在普通类和泛型类中都可以使用泛型方法
- 泛型方法的类型根据在使用时传入的参数类型而定
- 修饰符后没有跟类似< E >这样的形式的方法不是泛型方法
代码如下(示例):
public class Test {
public static void main(String[] args) {
A a = new A();
//泛型方法的类型根据在使用时传入的参数类型而定
a.run("abc");//此时E为String类型
a.run(1.4);//此时E为Double类型
a.run(true);//此时E为Boolean类型
}
}
//在普通类和泛型类中都可以使用泛型方法
class A{
public <E> void run(E e){
}
}
class B<K,T>{
public <E> void run(E e){
}
//修饰符后没有跟类似< E >这样的形式的方法不是泛型方法
//这是普通方法使用了泛型类中的泛型
public void work(K k){
}
}
三、泛型的继承和通配符
泛型不具备继承性。
例子:
List list = new ArrayList();//错误
通配符:
1、<?>:支持任意泛型类型
2、<? extends 父类类名(A)>: 表示上限,可以接受A类 或者 A类的子类
3、<? super 子类类名(A)> :表示下限,可以接受A类 或者 A类的父类