泛型,集合(含泛型)
一、泛型简介
泛型是一种我们常用的程序设计手段,使用泛型机制编写的程序代码要比那些杂乱的使用Object变量。然后进行强制类型转换的代码具有更好的安全性和可读性。泛型对于集合类尤其有用,例如,ArrayList就是一个无处不在的集合类
二、为什么要使用泛型程序设计
泛型程序设计意味着编写的代码可以被很多不同类型的对象所重用。例如,一个ArrayList类可以聚集任何类型的对象,这就是一个泛型程序设计的实例。
三、泛型的使用
1.集合中的使用
①在集合中不使用泛型的情况下,举一个例程:
@Test
public void test1() {
List list = new ArrayList();
list.add(85);
list.add(88);
list.add(70);
// 1.未使用泛型,可以加任何Object类型对象
list.add(new String("AA"));
for (int i = 0; i < list.size(); i++) {
// 强转错误,报ClassCastException
int score = (Integer) list.get(i);
System.out.println(score);// 此时new String转化错误
}
}
在IDE中,未使用泛型的集合会报warning,告诉开发者应使用泛型。并且当进行强制转换时,会产生一个异常。
②在集合中使用泛型的情况下,举一个例程:
// 2.在集合中使用泛型
@Test
public void test2(){
List<Integer> list = new ArrayList<>();
list.add(78);
list.add(87);
// list.add(new String("AA")); 错误!只能添加Integer类型的数据
// for (int i = 0; i < list.size(); i++) { //另一种遍历方式
// int score = list.get(i);
// System.out.println(score);
// }
Iterator<Integer> it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
运行后,不报warning,无异常发生。
2.自定义泛型类
一个泛型类就是具有一个或多个类型变量的类,以自定义Order类为例:
class Order<T> {
private String orderName;
private int orderId;
private T t;
List<T> list = new ArrayList<>();
public T getT() {
return t;
}
public void add() {
list.add(t);
}
@Override
public String toString() {
return "Order [orderName=" + orderName + ", orderId=" + orderId + ", t=" + t + "]";
}
public void setT(T t) {
this.t = t;
}
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
}
Order类引入了一个类型变量T,泛型类也可以有多个类型变量,例如:
class Order<T,U>{...}
类定义中的类型变量指定方法的返回类型以及域和局部变量的类型。例如:
private T t;
3.泛型方法
实际上,还可以定义一个带有类型参数的简单方法:
public <E> E getE(E e) {
return e;
}
注意,类型变量放在修饰符(此处为public)的后面,返回类型(此处为E)的前面。这样的方法称为泛型方法。
下面根据一个例程来了解自定义泛型类和泛型方法的使用
package generic;
import java.util.ArrayList;
import java.util.List;
//泛型类使用二:自定义泛型类
public class TestOrder {
// 自定义泛型类使用
public static void main(String[] args) {
Order<Boolean> order = new Order<>();
order.setT(true);
System.out.println(order.getT());
order.add();
List<Boolean> list = order.list;
System.out.println(list);
SubOrder o = new SubOrder();
List<Integer> list1 = o.list;
System.out.println(list1);
// 调用泛型方法
Integer i = order.getE(35);
Double d = order.getE(56.5);
Integer[] in = new Integer[] { 1, 2, 3 };
List<Integer> list2 = new ArrayList<>();
List<Integer> list3 = order.FromArrayToList(in, list2);
System.out.println(list3);
}
}
class Order<T> {
private String orderName;
private int orderId;
private T t;
List<T> list = new ArrayList<>();
public T getT() {
return t;
}
public void add() {
list.add(t);
}
// 泛型类使用三:声明泛型方法
public <E> E getE(E e) {
return e;
}
// 泛型方法:
public <E> List<E> FromArrayToList(E[] e, List<E> list) {
for (E e1 : e) {
list.add(e1);
}
return list;
}
@Override
public String toString() {
return "Order [orderName=" + orderName + ", orderId=" + orderId + ", t=" + t + "]";
}
public void setT(T t) {
this.t = t;
}
public String getOrderName() {
return orderName;
}
public void setOrderName(String orderName) {
this.orderName = orderName;
}
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
}
// 继承泛型类或者泛型接口时,可以指明泛型类型
class SubOrder extends Order<Integer> {
// 不指明:class SubOrder<T> extends Order<T>
}
四、泛型的继承规则
举个例子来说明继承规则
/*
* 泛型与继承的关系:
* 若类A是类B的子类,那么List<A>不是List<B>的子接口(类)
*/
@Test
public void test4(){
Object obj = null;
String str = "AA";
obj = str;
Object[] obj1 = null;
String[] str1 = new String[]{"AA","BB","CC"};
obj1 = str1; //非泛型
List<Object> list = null;
List<String> str2 = new ArrayList<>();
// list = str2; 错误!
}
若类A是类B的子类,那么List<A>不是List<B>的子接口(类),这就是泛型类的继承规则。即无论A,B有什么关系,通常List<A>与List<B>并没有什么联系。
五、通配符类型
当普通的类的继承不适用于泛型类时,为了实现继承关系,可使用通配符来完成
/*
* 通配符:?
* List<A>,List<B>...都是List<?>的子类
*
* ? extends A: 可以存放A及其子类
* ? super A:可以存放A及其父类
*/
@Test
public void test5(){
List<?> list = null;
List<Object> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
list = list1;
list = list2;
}