1.为什么要有泛型(Generic)?
①解决元素存储的安全性问题;
②解决获取数据元素时,需要类型强转的问题。
2.泛型的使用
2.1在集合中使用泛型
//1.在集合中没有使用泛型的情况下
@Test
public void test1(){
List list = new ArrayList();
list.add(89);
list.add(87);
list.add(67);
//①在没有使用泛型,任何Object及其子类的对象都可以添加进来
list.add(new String("AA"));
for(int i=0;i<list.size();i++){
//②强转为int型时,可能报ClassCastException的异常
int score = (Integer)list.get(i);
System.out.println(score);
}
}
//2.在集合中使用泛型
@Test
public void test2(){
List<integer> list = new ArrayList<integer>();
list.add(78);
list.add(87);
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());
}
}
@Test
public void test3(){
Map<string integer=""> map =new HashMap<string integer="">();
map.put("AA",78);
map.put("BB",87);
map.put("DD",98);
Set<Map.Entry<string integer="">> set =map.entrySet();
for(Map.Entry<string integer=""> o : set){
System.out.println(o.getKey() + "--->" + o.getValue());
}
}
2.2自定义泛型类、泛型接口、泛型方法
//自定义泛型类
public class Order<t>{
private String orderName;
private int orderId;
private T t;
List<t> list = new ArrayList<>();
public void add(){
list.add(t);
}
public T getT(){
return t;
}
public void setT(T t){
this.t = t;
}
//声明泛型方法
public<e> E getE(E e){
return e;
}
//实现数组到集合的复制
public<e> List<e> formArrayToList(E[] e,List<e> list){
for(E e1 :e){
list.add(e1);
}
return list;
}
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;
}
@Override
public String toString(){
return "Order [orderName="+orderName+",orderId="+orderId+",t="+t+"]";
}
}
//继承泛型类或泛型接口时,可以指明泛型的类型
class SubOrder extends Order<integer>{
}
或
class SubOrder<t> extends Order<t>{
}
自定义泛型类的使用
1.当实例化泛型类的对象时,指明泛型的类型。指明以后,对应的类中所有使用泛型的位置,都变为实例化中指定的泛型的类型。
2.如果我们自定义了泛型类,但是在实例化时没有使用,那么默认类型是Object类的
@Test
public void test4(){
Order<boolean> order = new Order<boolean>();
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(34);
Double d = order.getE(2.3);
Integer[] in new Integer[]{1,2,3};
List<integer> list2 = new ArrayList<>();
List<integer> list3 = order.formArrayToList(in,list2);
System.out.println(list3);
}
2.3泛型与继承的关系
//若类A是类B的子类,那么List<a>就不是List<strong>的子接口
@Test
public void test5(){
Object obj = null;
String str = "AA";
obj = str;
Object[] obj1 = null;
String[] str1 = new String[]{"AA","BB","CC"};
obj1 = str1;
List</strong></a><object> list = null;
List<string> list1 = new ArrayList<string>();
//list = list1;//错误(list与list1并列关系)
//假设list=list1满足
//list.add(123);
//String str = list1.get(0);//出现问题,所以假设不满足
}
2.4通配符
① 通配符 ?
- List<A>、List<B>、......都是List<?>的子类
- Collection<A>、Collection<B>、......都是Collection<?>的子类
- ?extends A :可以存放A及其子类
- ?super A :可以存放A及其父类
@Test
public void test6(){
List<?> list = null;
List<object> list1 = new ArrayList</object><object>();
List<string> list2 = new ArrayList<string>();
list = list1;
list = list2;
show(list1);
// show(list2);//错误
show1(list1);
show1(list2);
List<? extends Number> list3 = null;
List<integer> list4 = null;
list3 = list4;
// list3 = list1;
List<? super Number> list5 = null;
list5 = list1;
}
public void show(List<object> list){
}
public void show1(List<?> list){
}
②通配符的使用
这里使用了通配符?指定可以使用任何类型的集合作为参数。读取的元素使用了Object类型来表示,这是安全的,因为所有的类都是Object的子类。这里就又出现了另外一个问题,如下代码所示,如果试图往使用通配符?的集合中加入对象,就会在编译时出现错误。需要注意的是,这里不管加入什么类型的对象都会出错。这是因为通配符?表示该集合存储的元素类型未知,可以是任何类型。往集合中加入元素需要是一个未知元素类型的子类型,正因为该集合存储的元素类型未知,所以我们没法向该集合中添加任何元素。唯一的例外是null,因为null是所有类型的子类型,所以尽管元素类型不知道,但是null一定是它的子类型。
@Test
public void test7(){
List<string> list = new ArrayList<string>();
list.add("AA");
list.add("BB");
List<?> list1 = list;
//可以读取声明为通配符的集合类的对象
Iterator<?> iterator = list1.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
//不允许向声明为通配符的集合类中写入对象。唯一例外的是null
//list1.add("CC");//错误
//list1.add(123);//错误
list1.add(null);//正确
}