Java泛型是从JDK5中新加入的一个新特性。泛型提供了编译时类型安全检测机制,该机制可以在编译时检测到非法的类型。
泛型类
定义泛型类:
public class GenericClass<E> {
private E name;
public E getName() {
return name;
}
public void setName(E name) {
this.name = name;
}
}
测试:
public class DemoGenericClassTest {
public static void main(String[] args) {
GenericClass<Integer> gc = new GenericClass<>();
gc.setName(1);
Integer name = gc.getName();
System.out.println(name);
}
}
注:
- 泛型类可能有多个参数,此时应该将多个参数一起放在尖括号内,比如
<E1,E2,E3>
- 泛型类的构造器是:
public GenericClass(){}
,而不是public GenericClass<E>{}
泛型接口
语法:
修饰符 interface 接口名<代表泛型的变量>{}
定义含有泛型的接口:
/**
* 定义含有泛型的接口
*/
public interface GenericInterface<I> {
public abstract void method(I i);
}
使用含有泛型接口的第一种方式
创建类实现含有泛型的接口:
/**
含有泛型的接口,第一种使用方式:定义接口的实现类,实现接口,指定接口的泛型
*/
public class GenericInterfaceImpl1 implements GenericInterface<String> {
@Override
public void method(String s) {
System.out.println(s);
}
}
测试含有泛型的接口:
public class DemoGenericInterfaceTest {
public static void main(String[] args) {
GenericInterfaceImpl1 gi1 = new GenericInterfaceImpl1();
gi1.method("你好");
}
}
使用含有泛型接口的第二种方式
创建类实现接口:
/**
* 含有泛型的接口第二种使用方式:接口使用什么类型,实现类就使用什么泛型,类跟着接口走
* 就相当于定义一个含有泛型的类,创建对象的时候确定泛型的类型
*/
public class GenericInterfaceImpl2<I> implements GenericInterface<I> {
@Override
public void method(I i) {
System.out.println(i);
}
}
测试:
public class DemoGenericInterfaceTest {
public static void main(String[] args) {
GenericInterfaceImpl2<Integer> gi2 = new GenericInterfaceImpl2<>();
gi2.method(10);
}
}
泛型方法
语法:
修饰符 <代表泛型的变量> 返回值类型 方法名(参数){}
定义泛型方法:
public class GenericMethod {
public <M> void method1(M m) {
System.out.println(m);
}
public static <S> void method2(S s) {
System.out.println(s);
}
}
测试如下:
public class DemoGenericMethodTest {
public static void main(String[] args) {
//创建GenericMethod对象
GenericMethod gm = new GenericMethod();
gm.method1(10);
gm.method1("abc");
gm.method1(1.34);
//使用类名直接调用静态方法
GenericMethod.method2("def");
GenericMethod.method2(123);
}
}
泛型通配符
当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>
表示,一旦使用泛型的通配符,只能使用Object类中的共性方法,集合元素自身方法无法使用。
当不知道使用什么类型来接收的时候,此时可以使用?
,?
表示未知通配符。
/**
* 泛型的通配符
* ?: 代表任意的数据类型
* 使用方式:
* 不能创建对象使用
* 只能作为方法的参数使用
*/
public class DemoGeneric {
public static void main(String[] args) {
ArrayList<Integer> list01 = new ArrayList<>();
list01.add(1);
list01.add(2);
ArrayList<String> list02 = new ArrayList<>();
list02.add("a");
list02.add("b");
printArray(list01);
printArray(list02);
}
public static void printArray(ArrayList<?> list) {
Iterator<?> it = list.iterator();
while (it.hasNext()) {
Object o = it.next();
System.out.println(o);
}
}
}
泛型的上下限
泛型的上限:
-
类型名称<? extends 类> 对象名称
:只能接收该类型及其子类
泛型的下限:
-
类型名称<? super 类> 对象名称
:只能接收该类型及其父类型
import java.util.ArrayList;
import java.util.Collection;
/**
* 泛型的上限限定: ? extends E 使用的泛型只能是E类型的子类/本身
* 泛型的下限限定: ? super E 使用的泛型只能是E类型的父类/本身
*/
public class TestGeneric {
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);
}
//泛型的上限
public static void getElement1(Collection<? extends Number> coll) {
}
//泛型的下限
public static void getElement2(Collection<? super Number> coll) {
}
}