目录
一、泛型在集合中的使用:
① 集合接口或集合类在jdk5.0时都修改为带泛型的结构。 ② 在实例化泛型类时,可以指明具体的泛型类型 ③ 指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法、构造器、属性等)使用到类的泛型的位置,都指定为实例化的泛型类型。 比如:add(E e) --->实例化以后:add(Integer e) ④ 注意点:泛型的类型必须是类,不能是基本数据类型。需要用到基本数据类型的位置,拿包装类替换 ⑤ 如果实例化时,没有指明泛型的类型。默认类型为java.lang.Object类型。
二、泛型出现的意义
泛型出现以前的代码
@Test
public void test1() {
ArrayList arrayList = new ArrayList();
arrayList.add(23);
arrayList.add(66);
arrayList.add(54);
arrayList.add(78);
// 问题一:类型不安全
arrayList.add("tom");
for (Object obj : arrayList) {
// 问题二:强转时可能会出现ClassCastException
int score = (int) obj;
System.out.println(score);
}
}
泛型出现之后的代码
@Test
public void test2() {
ArrayList<Integer> list = new ArrayList<>();
list.add(52);
list.add(23);
list.add(67);
list.add(98);
// list.add("tom");编译不通过
// 遍历方式一
for (Integer score : list) {
int stuScore = score;//避免了强转操作
System.out.println(stuScore);
}
// 遍历方式二
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
三、自定义泛型类、自定义泛型方法
public class Order<T> {
String name;
int age;
T orderT;
public void makeArr() {
//编译不通过
// T[] arr = new T[10];
//编译通过
T[] arr = (T[]) new Object[10];
}
// 泛型方法:在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系。
// 泛型方法和类没有什么关系
public <E> List<E> copyhhh(E[] arr){
ArrayList<E> list = new ArrayList<>();
for(E e : arr ){
list.add(e) ;
}
return list;
}
调用自定义的泛型类和泛型方法
@Test
public void test1() {
//如果定义了泛型类,实例化没有指明类的泛型,则认为此泛型类型方object类型
//要求:如果大家定义了类是带泛型的,建议在实例化时要指明类的泛型。
Order<String> a = new Order<String>("tom",12,"hhh");
a.setOrderT("ksjfdkls");
}
// 调用泛型方法
@Test
public void test2(){
Order<String> order = new Order<>();
Integer[] arr = new Integer[]{1,4,5,6,78};
//泛型方法调用时,指明泛型的类型,
// 泛型参数实在调用方法时确定的,不是在实例化类的时候确定的,所以泛型方法可以是static的
List<Integer> copyhhh = order.copyhhh(arr);
System.out.println(copyhhh);
}
四、泛型类的两种子类
1、如果父类没有指明泛型的类型,那就子类也不指明,在类的内部使用时再指明 由于泛型的使用是在创建对象时,所以泛型类中的静态方法不能使用泛型,因为静态方法与类同时出现的 异常类不能时泛型的
public class SubOrder2<T> extends Order<T>
2、父类指明了泛型的类型,子类不用泛型,直接是父类的泛型的类了
public class SubOrder extends Order<Integer>
五、泛型在继承方面的特点
类A是类B的父类,G<A>和G<B>二者不具备子父类关系,二者是并列关系。 补充:类A是类B的父类,A<G>是B<G>的父类
@Test
public void test1() {
List<Object> list1 = null;
List<String> list2 = null;
// list1 = list2;出错了 此时的list1 和 list2 不具备子父类关系
}
那么他俩有什么关系呢,于是有了通配符,作为这两个的父类出现 ----->
六、通配符的使用: ?
类A是类B的父类,G<A>和G<B>是没有关系的,二者共同的父类是:G<?> 此时写入数据和读取数据时: 添加操作:对于List<?>就不能向其内部添加数据。 除了添加null; 获取操作:可以获取,获取的类型为Object的 有限制条件的通配符的使用 ? extends A: 负无穷到A ?泛型的范围小于等于A 不能进行添加操作 ? super A: A到正无穷 ?泛型的范围大于等于A 能进行添加操作,添加的类型只能是A或者A的子类