- 概述
- 泛型的使用
- 泛型变量的类型限定
- 通配符的边界限定
- 泛型使用的限制
1、概述
泛型是JDK1.5的新特性,其本质是参数化类型,即所操作的数据类型被指定为一个参数,使用时通过传参来指定具体的类型。泛型提供了编译时类型安全监测机制,该机制允许程序员在编译时监测非法的类型,对比强制类型转换具有更好的安全性和可读性。泛型在集合类中尤其有用,例如ArrayList:
ArrayList list1 = new ArrayList();
list1.add("不使用泛型");
String str1 = (String) list1.get(0);
ArrayList<String> list2 = new ArrayList<>();
list2.add("使用泛型");
String str2 = list2.get(0);
2、使用
泛型有三种常用的使用方式:泛型类、泛型接口和泛型方法,下面来分别介绍这三种方式的使用。
(1)泛型类
泛型类:public class 类名<泛型类型1,…>,一个泛型类就是具有一个或多个类型变量的类。
/*
泛型类
java库中,E 表示集合的元素类型,K 和 V 分别表示表的关键字和值的类型
T 表示任意类型,需要时也可以用临近的字母 U 和 S
* */
public class Book<T> {
private T name;
private T type;
public Book(T name, T type) {
this.name = name;
this.type = type;
}
public T getName() {
return name;
}
public void setName(T name) {
this.name = name;
}
public T getType() {
return type;
}
public void setType(T type) {
this.type = type;
}
}
//测试
//注意:泛型的类型参数只能是类类型
/传入的实参类型需与泛型的类型参数类型相同
Book<String> book = new Book<String>("悲惨世界","世界名著");
String name = book.getName();
String type = book.getType();
Log.d(TAG,name+":"+type);
Book<Integer> book1 = new Book<Integer>(1,2);
Integer name1 = book1.getName();
Integer type1 = book1.getType();
Log.d(TAG,name1+":"+type1);
(2)泛型接口
泛型接口:public interface 接口名<泛型类型1,…>。
public interface BookImpl<T,U> {
void show(T t,U u);
}
public class BookController implements BookImpl<String, Date> {
@Override
public void show(String s, Date date) {
Log.d("泛型接口测试:",s+":"+date.toString());
}
}
BookController bookController = new BookController();
bookController.show("三年高考五年模拟",new Date());
(3)泛型方法
泛型方法:public <泛型类型1,…> 返回类型 方法名(泛型类型1 参数1,…)。
//泛型方法
public class BookUtil {
public <T> T show(T t) {
if (t != null) {
return t;
} else {
return null;
}
}
}
//测试
BookUtil bookUtil = new BookUtil();
String str = bookUtil.show("泛型方法");
Log.d(TAG,str);
3、泛型变量的类型限定
使用extends关键字,限定的是形式参数:
//表示只接受Number及其子类的参数
public class Test<T extends Number> {
}
4、通配符"?"的边界限定
配合extends和super关键字,限定的是实际参数:
(1)List<?>:等效于List<? extends Object>,表示不受限。
(2)List<? extends Number>:上边界限定,表示只接受Number及其子类类型的参数。
(3)List<? super Number>:下边界限定,表示只接受Number及其父类类型的参数。
5、使用限制
(1)不能用基本类型实例化泛型。
//正确
Book<Integer> book1 = new Book<Integer>(1,2);
//错误
Book<int> book1 = new Book<int>(1,2);
(2)不能使用static修饰泛型类型。
//错误
private static T name;
(3)不能对参数化类型进行强转,除非是无界通配符类型。
List<Integer> arrayList = new ArrayList<>();
//正确
List<?> list= arrayList;
//错误
List<Number> numberList = (List<Number>)arrayList;
(4)不能对参数化类型使用instanceof,除非是无界通配符类型。
public static <E> void test(List<E> list) {
//错误
if (list instanceof ArrayList<Integer>) {
}
//正确
if (list instanceof ArrayList<?>) {
}
}
(5)不能创建参数化类型的数组。
//错误
ArrayList<String>[] arrayList = new ArrayList<String>[3];
(6)不能创建、捕捉或抛出参数化类型的对象。
//错误
class MathException<T> extends Exception {}
//错误
class QueueFullException<T> extends Throwable {}
public static <T extends Exception, J> void execute(List<J> jobs) {
try {
//错误
} catch (T e) {
}
}
(7)不能重载参数类型为相同原始类型的方法,因为擦除后是一样的。
//错误
public class Test{
public void test(List<String> list) {}
public void test(List<Integer> list) {}
}