目录
一、概念
/**
* 在实例化集合类时,可以指明具体的泛型类型
* 泛型的类型必须是类,不能是基本数据类型。需要用到基本数据类型的位置,使用包装类
* 如果实例化没有使用泛型,默认类型为java.lang.Object类型
*/
@Test
public void test(){
//在集合中使用泛型:ArrayList
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(12);
list.add(1);
list.add(2);
list.add(0);
//遍历方式一:采用foreach
for (Integer score : list) {
System.out.println(score);
}
//遍历方式二:采用Iterator
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()){
Integer stuScore = iterator.next();
System.out.println(stuScore);
}
}
* 集合的输出利用Iterator接口完成;Map没有提供直接的Iterator接口
* 使用Collection保存数据,直接保存所有对象
* 使用Map保存数据时,所保存的key和value自动包装成Map.Entry接口对象
*
* Map利用Iterator:
* 1、利用entrySet()方法将Map中的数据转换为Set接口实例;
* 2、使用Set中的迭代iterator()方法
* 3、每一次迭代都是取出Map.Entry接口实例,在创建该接口实例,调用getKey()
* getValue()方法获取相应的key-value值
//HashMap中使用泛型
@Test
public void test1(){
//直接指定key-value的类型
HashMap<String, Integer> map = new HashMap<>();
map.put("aa",100);
map.put("bb",900);
map.put("cc",200);
map.put("dd",300);
map.put("ee",400);
Set<Map.Entry<String, Integer>> set = map.entrySet();
Iterator<Map.Entry<String, Integer>> iterator = set.iterator();
while (iterator.hasNext()){
Map.Entry<String, Integer> e = iterator.next();
System.out.println(e.getKey() + "==" + e.getValue());
}
}
二、自定义泛型类
父类为泛型类
//泛型类
class Order<T> {
String name;
int Id;
//类的内部结构可以使用类的泛型
T orderT;
public Order(){}
public Order(String name, int Id, T orderT) {
this.name = name;
this.Id = Id;
this.orderT = orderT;
}
public T getOrderT() {
return orderT;
}
public void setOrderT(T orderT) {
this.orderT = orderT;
}
@Override
public String toString() {
return "GenericClass{" +
"name='" + name + '\'' +
", Id=" + Id +
", orderT=" + orderT +
'}';
}
}
子类继承泛型类:
//subOrder1是泛型类
class subOrder1<T> extends Order<T>{}
//subOrder继承Order 并指明泛型<Integer> 此时subOrder不是泛型类
class subOrder extends Order<Integer>{}
//实例化 泛型类 时 指明为String类型
Order<String> order1 = new Order<String>("marry",22,"aa");
//子类在继承带泛型的父类时,已经指明了泛型,则在实例化时不需要指明了
subOrder subOrder = new subOrder();
subOrder.setOrderT(123);
//在继承时为指明类型 则实例化需要指明类型
subOrder1<String> subOrder1 = new subOrder1<>();
subOrder1.setOrderT("string类型");
子类继承泛型类的情况:
class Father<T1,T2>{}
//子类不保留父类的泛型
//(1)没有类型,擦除
class son1 extends Father{}
//(2)具体类型
class son2 extends Father<Integer,String>{}
//子类保留父类的泛型
//(1)全部保留
class son3<T1,T2> extends Father<T1,T2>{}
//(2)部分保留
class son4<T2> extends Father<Integer,T2>{}
class Father<T1,T2>{}
//子类不保留父类的泛型
//(1)没有类型,擦除
class son1<A,B> extends Father{} //子类另外指明泛型
//(2)具体类型
class son2<A,B> extends Father<Integer,String>{}
//子类保留父类的泛型
//(1)全部保留
class son3<T1,T2,A,B> extends Father<T1,T2>{}
//(2)部分保留
class son4<T2,A,B> extends Father<Integer,T2>{}
三、泛型类
/**
* 泛型方法:不一定要在泛型类中定义;在方法的返回值前定义了泛型的标记
* 可以声明为static,因为在调用该方法时才确定泛型参数的类型,而不是在实例化确定
*/
在Order泛型类中声明一个泛型方法,其中泛型方法的泛型参数E与该类的泛型参数T没有关系
泛型方法1:
//返回值是一个List,并且声明为泛型结构
//传入T类型的数组:比如形参int[] arr 则返回值为int型的集合
//此处可以将该方法声明为static,因为泛型方法与所处的类没有关系,在该方法调用的时候才确定泛型参数的类型
public static <E> List<E> show(E[] arr){
ArrayList<E> list = new ArrayList<>();
for(E t : arr){ //遍历arr,并将arr的每一值赋给T类型的变量t
list.add(t); //将变量t添加到集合list中去
}
return list;
}
//测试泛型方法
@Test
public void test(){
//泛型类指明为String类型
Order<String> order = new Order<>();
//声明一个double型的数组
Double[] arr = {1.0, 2.0, 4.5, 6.8};
//调用泛型类中的泛型方法,在调用时,指明泛型参数的类型
List<Double> list = order.show(arr);//与类的泛型参数可以无关
System.out.println(list); //[1.0, 2.0, 4.5, 6.8]
}
泛型方法2:
//定义返回值类型为A的泛型方法
public <A> A method(A a){
return a;
}
//调用泛型方法
int i = 6;
System.out.println(order.method(i)); //6
四、通配符
一般形式的通配符:
/**
* 通配符的使用:
* 通配符:?
* 类A是类B的父类,G<A>和G<B>是无关系的,二者共同的父类是G<?> G<A>:泛型参数为A类型
*/
List<Object> list1 = null;
List<String> list2 = null;
List<?> list = null;
//比如:Object是String的父类,但是list1与list2没有关系,而list可作为list1与list2共同的
父类,从而进行赋值操作,相当于向上转型
list = list1;
list = list2;
List<String> list3 = new ArrayList<>(); //List接口实例化,泛型类型为String类型
list3.add("aa");
list3.add("ab");
list3.add("bb");
list = list3;
//对于list<?>不能添加数据,但可以添加null
list.add(null);
//获取,获取到的数据类型为Object
Object o = list.get(0); //赋给最高级父类(防止传进来的参数类型低于接收的类型,从而报错)
System.out.println(o);
有限制条件的通配符:
/**
* 有限制条件的通配符
* ? extends A
* G<? extends A> 可以作为G<A> 和 G<B>的父类,其中B是A的子类
*
* ? super A
* G<? extends A> 可以作为G<A> 和 G<B>的父类,其中B是A的父类
*/
public class GenericTest3 {
@Test
public void test(){
List<? extends Person> list1 = null;
List<? super Person> list2 = null;
List<Student> list3 = null;
List<Person> list4 = null;
List<Object> list5 = null;
//list1只能接收Person或它的子类 类型的结构(在读取数据时,接收类型要是最高的级别)
list1 = list3;
list1 = list4;
// list1 = list5; 错误
//list2只能接收Person或它的父类Object 类型的数据(在读取数据时,接收类型要是最高的级别)
// list2 = list3; 错误
list2 = list4;
list2 = list5;
}
}
class Person{}
class Student extends Person{}