泛型
概述
集合中未使用泛型的情况
- 问题一:类型不安全
- 问题二:强转时,可能出现异常ClassCastException
package com.zzb;
import org.junit.Test;
import java.util.ArrayList;
public class Demo1 {
//在集合中使用泛型之前的情况:
@Test
public void test1() {
ArrayList list = new ArrayList();
list.add(23);
list.add(24);
list.add(36);
list.add(75);
//问题一:类型不安全
list.add("Tom");
//遍历
for (Object score : list) {
//问题二:强转时,可能出现异常ClassCastException
int stuScore = (Integer) score;
System.out.println(stuScore);
}
}
}
集合使用泛型的情况
- 集合接口或集合类在jdk5.0时都修改为带泛型的结构.
- 在实例化集合类时,可以指明具体的泛型类型
- 指明泛型以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法,构造器,属性等)使用到类的泛型的位置,都指定为实例化的泛型类型.比如:add(E e)方法 实例化后:add(integer e)
- 注意点:泛型的类型必须是类,不能是基本数据类型.需要用到基本数据类型的位置,拿包装类替换.
- 如果实例化时,没有指明泛型的类型.默认类型为java.lang.Object类型.
package com.zzb;
import org.junit.Test;
import java.util.*;
public class Demo2 {
//在集合中使用泛型的情况,以ArrayList为例
@Test
public void test1() {
ArrayList<Integer> list = new ArrayList<>();
list.add(35);
list.add(56);
list.add(47);
list.add(69);
//编译时,就会进行类型检查,保证数据的安全.
// 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());
}
}
//在集合中使用泛型的情况,以HashMap为例
@Test
public void test2() {
HashMap<String, Integer> map = new HashMap<>();
map.put("Tom", 86);
map.put("Jone", 66);
map.put("Jerry", 96);
// map.put(123, "Tom");
//泛型的嵌套
Set<Map.Entry<String, Integer>> set = map.entrySet();
Iterator<Map.Entry<String, Integer>> iterator = set.iterator();
while (iterator.hasNext()) {
Map.Entry<String, Integer> entry = iterator.next();
Integer value = entry.getValue();
String key = entry.getKey();
System.out.println(key + "==" + value);
}
}
}
如何自定义泛型结构
泛型类 泛型接口
- 如果定义了泛型类,实例化没有指明类的泛型,则认为此泛型类型为Object类型.
- 要求:如果定义了类是带泛型的,建议在实例化时要指明类的泛型.
- 由于子类在继承带泛型的父类时,指明了泛型类型,则实例化子类对象时,不再需要指明泛型.
package com.zzb;
import org.junit.Test;
public class Demo3 {
@Test
public void test1() {
Order order = new Order();
order.setOrderT(123);
order.setOrderT("123");
//实例化时指明类的泛型
Order<String> order1 = new Order<String>("AA", 1001, "123");
order1.setOrderT("Hello");
}
@Test
public void test2() {
SubOrder subOrder = new SubOrder();
subOrder.setOrderT(13);
SubOrder1<String> subOrder1 = new SubOrder1<>();
subOrder1.setOrderT("hello");
}
}
//自定义泛型类
class Order<T> {
String orderName;
int orderId;
//类的内部结构就可以使用类的泛型
T orderT;
public Order() {
}
public Order(String orderName, int orderId, T orderT) {
this.orderName = orderName;
this.orderId = orderId;
this.orderT = orderT;
}
public T getOrderT() {
return orderT;
}
public void setOrderT(T orderT) {
this.orderT = orderT;
}
@Override
public String toString() {
return "Order{" +
"orderName='" + orderName + '\'' +
", orderId=" + orderId +
", orderT=" + orderT +
'}';
}
}
class SubOrder extends Order<Integer> {//不是泛型类
}
class SubOrder1<T> extends Order<T> {//是泛型类
}
泛型方法
- 泛型方法:在方法中出现了泛型的结构,泛型参数与类的泛型参数没有任何关系.(泛型方法所属的类是不是泛型类都没有关系).
- 泛型方法,可以声明为静态的,原因: 泛型参数是在调用方法时确定的,并非在实例化类时确定.
class SubOrder1<T> extends Order<T> {//是泛型类
public <E> List<E> copyToList(E[] arr) {
ArrayList<E> list = new ArrayList<>();
for (E e : arr) {
list.add(e);
}
return list;
}
}
public class Demo3 {
@Test
public void test3() {
SubOrder1<Object> subOrder1 = new SubOrder1<>();
Integer[] arr = {1, 2, 23, 4};
List<Integer> integers = subOrder1.copyToList(arr);
System.out.println(integers);
}
}
通配符的使用 (通配符:?)
- 类A是类B的父类,G(A)和G(B)是没有关系的,二者共同的父类是:G(?)