泛型
泛型
一、泛型概述
- 泛型是一种未知的数据类型,当我们不知道使用什么数据类型的时候,可以使用泛型;
- 泛型也可以看成是一个变量,用来接收数据类型;
- E e:Element 元素
- T t:Type 类型
二、泛型的定义与使用
2.1 定义和使用含有泛型的类
定义格式:
修饰符 class 类名<泛型>{}
例如:
public class GenericClass<E> {
private E name;
public GenericClass() {
}
public GenericClass(E name) {
this.name = name;
}
public E getName() {
return name;
}
public void setName(E name) {
this.name = name;
}
}
使用泛型:在创建对象的时候确定泛型
public class Demo01 {
public static void main(String[] args) {
GenericClass<String> genericClass = new GenericClass<>();
genericClass.setName("创建对象即确定泛型");
String name = genericClass.getName();
}
}
2.2 含有泛型的方法
定义格式:
修饰符 <泛型> 返回值类型 方法名(参数){}
public static <T> T method(){}:第一个<T>代表泛型变量类型,第二个T代表返回值类型。
例如:
public class GenericMethod {
//定义一个含有泛型的方法
public <M> void method01(M m) {
System.out.println(m);
}
//定义一个含有泛型的静态方法
public static <S> void method02(S s) {
System.out.println(s);
}
}
使用格式:调用方法时,确定泛型的类型
public class Demo02 {
public static void main(String[] args) {
GenericMethod gm = new GenericMethod();
gm.method01("字符串");
gm.method01(123);
gm.method01(false);
GenericMethod.method02("静态方法");
GenericMethod.method02(111);
}
}
2.3 含有泛型的接口
定义格式:
修饰符 interface 接口名<泛型>{}
例如:
public interface GenericInterface<I> {
public abstract void method(I i);
}
使用格式:
2.3.1 定义类时确定泛型的类型
例如:
public class GennericInterfaceImpl1 implements GenericInterface<String> {
@Override
public void method(String s) {
System.out.println(s);
}
}
2.3.2 创建对象时确定泛型的类型(常用)
例如:
/**
* 含有泛型的接口第二种使用方式:接口使用什么泛型,实现类就使用什么泛型。
* 就相当于定义了一个含有泛型的类,创建对象的时候确定泛型的类型
*/
public class GennericInterfaceImpl2<I> implements GenericInterface<I> {
@Override
public void method(I i) {
System.out.println(i);
}
}
public class Demo03 {
public static void main(String[] args) {
GennericInterfaceImpl1 impl1 = new GennericInterfaceImpl1();
impl1.method("字符串");
GennericInterfaceImpl2<Integer> impl2 = new GennericInterfaceImpl2<>();
impl2.method(100);
GennericInterfaceImpl2<String> impl3 = new GennericInterfaceImpl2<>();
impl3.method("创建对象时确定泛型类型");
}
}
三、泛型通配符(?)
3.1 通配符基本使用
泛型的通配符:不知道什么类型来接收的时候,此时可以使用?,?表示未知通配符。
例如:泛型没有继承概念
/**
* 泛型的通配符:
* ?:代表任意的数据类型
* 使用方式:
* 不能创建对象使用
* 只能作为方法的参数使用
*/
public class Demo04Generic {
public static void main(String[] args) {
ArrayList<Integer> list01 = new ArrayList<>();
list01.add(10);
list01.add(20);
ArrayList<String> list02 = new ArrayList<>();
list02.add("a");
list02.add("b");
printArray(list01);
printArray(list02);
}
/*
定义一个方法,能遍历所有类型的ArrayList集合
此时我们不知道ArrayList集合使用什么数据类型,就可以使用泛型的通配符<?>来接收数据类型
注意:
泛型没有继承概念(即方法入参不能用ArrayList<Object>来接收)
*/
public static void printArray(ArrayList<?> arrayList){
for (Object i : arrayList) {
System.out.println(i);
}
}
}
3.2 通配符高级使用——受限泛型
之前设置泛型的时候,实际上是可以任意设置的,只要是类就可以设置,但是在JAVA的泛型中可以指定一个泛型的上限和下限。
3.2.1 泛型的上限
- 格式:
类型名称<? extends 类名> 对象名称 - 意义:
只能接收该类型及其子类
3.2.2 泛型的下限
- 格式:
类型名称<? super 类名> 对象名称 - 意义:
只能接收该类型及其父类
比如:现已知Object类,String类,Number类,Integer类,其中Number是Integer的父类
public class Demo05Generic {
public static void main(String[] args) {
Collection<Integer> list1 = new ArrayList<>();
Collection<String> list2 = new ArrayList<>();
Collection<Number> list3 = new ArrayList<>();
Collection<Object> list4 = new ArrayList<>();
getElement1(list1);
getElement1(list2);//报错
getElement1(list3);
getElement1(list4);//报错
getElement2(list1);//报错
getElement2(list2);//报错
getElement2(list3);
getElement2(list4);
}
// 泛型的上限:此时的泛型?,必须是Number类型或其子类
public static void getElement1(Collection<? extends Number> coll){}
// 泛型的下限:此时的泛型?,必须是Number类型或其父类
public static void getElement2(Collection<? super Number> coll){}
}

浙公网安备 33010602011771号