一、泛型的概念
1.什么是泛型,看表面的意思,泛型就是指广泛的、普通的类型
2. 所谓泛型,就允许在定义类、接口时通过圆滚滚标识表示类中的某个属性的类型或者某个方法的返回值及参数类型。
这个参数类型将在使用的时候就确定了。
使用泛型有哪些好处
(1)首先就像上面那个例子一样,使用泛型能够限定集合中,如List, Set中元素的类型,保证一个集合中只有一个类型。
(2)程序也能更加健壮(只要在编译时期没有出现警告,那么运行时期就不会出现ClassCastException异常)
二、泛型的使用
1.jdk5.0新增的特性
2.集合中使用泛型
①在集合接口或集合类中在jdk5.0时都修改为带泛型的结构。
②在实例化集合类时,可以指明泛型的类型
③指明完后,在集合类或者接口中凡是定义类和接口时,内部结构都使用到类的泛型的位置,都指定为实例化时的泛型类型
比如:add(E e)----->实例化后add(Integer e)
④泛型的类型必须是类,不能是基本数据类型需要用到基本数据类型的时候,使用它的包装类
⑤如果实例化时,没有指定泛型类型,默认为Object类型
3、自定义泛型结构:泛型类、泛型接口、泛型方法
4.自定义泛型的注意
在集合中使用泛型之前的情况:
ArrayList list = new ArrayList();
list.add(10);
list.add(20);
list.add(30);
list.add(40);
list.add(50);
//其他类型出现
//问题一、类型不安全
// list.add("Tom");
for (Object score : list){
//问题2:出现异常,ClassCastException
int stuScore = (int)score;
System.out.println(stuScore);
}
在集合中使用泛型的情况:
泛型是一个类型,但是不能是基本数据类型,所有需要使用包装类
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(60);
list.add(70);
list.add(80);
list.add(90);
list.add(100);
//编译时,就会进行类型检查,保证数据的安全性
// list.add("Tom");
//方式一
for (Integer score:list){
//避免了强转出现的异常
int stuScore = score;
}
//方式二
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()){
// System.out.println(iterator.next());
int next = iterator.next();
System.out.println(next);
}
在集合中使用泛型的情况:以HashMap为例
Map<String,Integer> map = new HashMap<String ,Integer>();
map.put("Tom",123);
map.put("Tom1",123);
map.put("Tom2",456);
map.put("Tom3",789);
map.put("Tom4",159);
//编译错误
// map.put(741,"Tmo5")
//泛型的嵌套Entry为Map的内部接口
Set<Map.Entry<String, Integer>> entries = map.entrySet();
Iterator<Map.Entry<String, Integer>> iterator = entries.iterator();
while (iterator.hasNext()){
Map.Entry<String, Integer> next = iterator.next();
System.out.println(next);//Tom=123键值
String key = next.getKey();
Integer value = next.getValue();
System.out.println("key = " + key + ",value = " + value);//key = Tom,value = 123 键和值
}
三、自定义泛型类
注意事项:
自定义泛型类
public class Order<T> {
String orderName;
int orderId;
//类的内部结构,就可以使用类的泛型
T orderT;
public Order(){
//编译不通过
// T[] arr = new T[20]
}
public Order(String orderName,int orderId,T orderT){
this.orderName =orderName;
this.orderId =orderId;
this.orderT = orderT;
}
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;
}
//如下的三个方法都不是泛型方法
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 +
'}';
}
//静态方法中不能使用类的泛型
// public static void show(T orderT){
// System.out.println(orderT);
// }
public void show(){
//编译不通过,泛型不能时异常类型
// try {
//
// }catch (T t){
//
// }
}
//泛型方法,在方法中出现了泛型的结构,泛型的参数与类的泛型参数没有任何关系。
// public static <E> List<E> copy(E[] arr){}
//泛型方法,在不在泛型类中都没有关系
//泛型方法可以是静态的:原因:泛型参数是在调用时确定的,并不是在实例化时确定的。
public static <E> List<E> copy(E[] arr){
ArrayList<E> list = new ArrayList<>();
for (E e:arr){
list.add(e);
}
return list;
}
}
不是泛型类只是继承了泛型
public class SubOrder extends Order<Integer> {//不是泛型类
//泛型方法,在不在泛型类中都没有关系
public static <E> List<E> copy(E[] arr){
ArrayList<E> list = new ArrayList<>();
for (E e:arr){
list.add(e);
}
return list;
}
}
这种也是泛型类
public class SubOrder1 extends Order {//泛型类
}
1.如果定义了泛型类,实例化时没有指定类的泛型,则认为泛型的类型为Object类型
// Order order = new Order();
// order.setOrderT(123);
// order.setOrderT("ABC");
//要求,如果定义了为带泛型的类,建议在实例化时要指明泛型的类型
// Order<Integer> order = new Order<Integer>();
// order.setOrderT(123);
//带上泛型后,指明了类型
// order.setOrderT("ABC");
Order<String> order = new Order<>("orderAA", 1001, "order:AA");
order.setOrderT("AA:hello");
// order.setOrderT(123);
2.由于子类在继承带泛型的父类时,指明了泛型的类型,则在子类实例化时,不在需要指明泛型的类型
SubOrder subOrder = new SubOrder();
subOrder.setOrderId(123);
SubOrder1<Integer> subOrder1 = new SubOrder1<Integer>();
// subOrder1.setOrderT("AA");
subOrder1.setOrderT(123);
3.泛型不同的引用不能互相复制
ArrayList<Integer> list1 = null;
ArrayList<String > list2 = null;
//编译报错,类型不同
// list1 = list2;
4.测试泛型方法
Order<String> order = new Order<>();
Integer[] arr = new Integer[]{1,2,3,4};
//泛型方法在调用时,指明泛型参数的类型
List<Integer> copy = order.copy(arr);//自定义泛型类中有该方法
System.out.println(copy);//[1, 2, 3, 4]
四、泛型在继承方面的体现
虽然类A是类B的父类,但是G< A > 和 G < B > 二者不是父类,为并列关系
类A是类B的父类 A< G > 是 B< G >的父类
@Test
public void test(){
Object obj = null;
String str = null;
obj = str;
List<Object> list1 = null;
List<String> list2 = null;
//编译错误,类型不具备子父的关系
// list1 = list2
show(list1);
show1(list2);
}
public void show(List<Object> list){
}
public void show1(List<String> list){
}
类型相同,编译才不会报错
List<String > list = null;
ArrayList<String> list1 = null;
list = list1;
通配符的使用 通配符:?
类A是类B的父类,但是G< A > 和 G< B >为并列关系,二 者 共 同 的 父 类 为 G < ?>
List<Object> list1 = null;
List<String> list2 = null;
List<?> list = null;
list = list1;
list = list2;
//编译通过
// print(list1);
// print(list2);
//使用通配符后,数据的读写要求
List<String > list3 = new ArrayList<>();
list3.add("AA");
list3.add("BB");
list3.add("CC");
list =list3;
//添加(写入)报错,对于List<?>就不能向其内部添加数据,除了null以外
// list.add("DD");
list.add(null);
//获取(读取):允许读取数据,读取的类型为Object
Object o = list.get(0);
System.out.println(o);
public void print(List<?> list){
Iterator<?> iterator = list.iterator();
while (iterator.hasNext()){
Object next = iterator.next();
System.out.println(next);
}
}
有限制条件的通配符使用
Student类继承自Person
? extends Person
? super Student
? extends A :G< ? extends A > 可以看作G< A > 和 G < B >的父类,其中B是A的子类
? super A:G< ? super A> 可以作为G< A > 和 G< B >的父类,其中B是A的子类
练习、如果遍历Map的key集,value集,key-value集,使用上泛型
Map<String,Integer> map = new HashMap<String ,Integer>();
map.put("Tom",123);
//获取key集
Set<String> strings = map.keySet();
for (String key:strings){
System.out.println(key);
}
//遍历value集
Collection<Integer> values = map.values();
Iterator<Integer> iterator = values.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
//遍历key-value集
Set<Map.Entry<String, Integer>> entries = map.entrySet();
Iterator<Map.Entry<String, Integer>> iterator1 = entries.iterator();
while (iterator1.hasNext()){
Map.Entry<String, Integer> next = iterator1.next();
String key = next.getKey();
Integer value = next.getValue();
System.out.println(key +" +++++++++ " + value);
}
//提供一个方法用于遍历获取HashMap<String,String>中的所有value,并存放到list集合中返回,使用泛型
public List<String> getValueList(HashMap<String,String> map){
ArrayList<String > valueList = new ArrayList<>();
Collection<String> values =map.values();
for (String value :values){
valueList.add(value);
}
return valueList;
}
五、泛型在开发中的使用场景
DAO:data(base) access object 数据访问对象
public class DAO<T> {
//添加
public void add(T t){
}
//删除
public boolean remove(int index){
return false;
}
//修改
public void update(int index,T t){
}
//查询
public T getIndex(int index){
return null;
}
//查询多条记录
public List<T> getForList(int index){
return null;
}
}