Java基础-复习09-泛型

一. 概述

1. 什么是泛型?

泛型:将还未知的类型参数化(类型形参)并用大写字母作为临时标识,然后在调用时再传入具体的类型(类型实参)。泛型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。

2. 为什么引入泛型?

集合容器类在设计阶段/声明阶段不能确定这个容器到底实际存的是什么类型的对象,这个时候元素的类型不确定,因此把元素的类型设计成一个类型参数:泛型(JDK1.5引入)。Collection< E >,List< E >,ArrayList< E > 这个 < E > 就是类型参数,即泛型。

借一个栗子:

//未用泛型
List arrayList = new ArrayList();
arrayList.add("abc");
arrayList.add(123);
for(int i = 0; i < arrayList.size(); i++){
     
	String item = (String)arrayList.get(i); 
	System.out.println(item)} //java.lang.ClassCastException:java.lang.Integer cannot be cast to java.lang.String
-------------------------------------------------------------------------------------
//加入泛型
List<String> arrayList = new ArrayList();
arrayList.add("abc");
arrayList.add(123); //在编译阶段会报错

Java基础-复习09-泛型_第1张图片
Java基础-复习09-泛型_第2张图片

有了泛型,解决了获取数据元素时,需要类型强制转换的问题,同时保证了如果程序在编译时没有发岀警告,运行时就不会产生 ClassCastException 异常。

二. 使用泛型

1. 泛型类

泛型类的类型参数声明部分包含一个或多个类型参数,参数间用逗号隔开,典型的就是各种容器类,如HashMap

自定义泛型类

class Order<T>{
     
	private String name;
	private int id;
	private 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;
	}
}

@Test
//实例化时指明类的类型,否则默认为 Object 类型
public void test(){
     
	Order<String> order1 = new Order<>();
	Order<String> order2 = new Order<>("TOM", 16, "Male");
	.
	.
}

2. 泛型接口

泛型接口与泛型类的定义及使用基本相同,泛型接口常被用在各种类的生产器中

//定义一个泛型接口
public interface Generator<T>{
     
    public T next();
}

3. 泛型方法

  • 泛型类,是在实例化类的时候指明泛型的具体类型
  • 泛型方法,是在调用方法的时候指明泛型的具体类型

泛型方法格式:访问权限 <泛型> 返回类型 方法名(泛型标识 参数名称) 抛出的异常

//方法里的泛型参数与类的泛型参数没有任何关系
public <E> List<E> copyFromArryToList(E[] arr) {
     
    ArrayList<E> list = new ArrayList<>();
    for (E e : list){
     
        list.add(e);
    }
    return list;
}

无论何时,如果你能做到,你就该尽量使用泛型方法。也就是说,如果使用泛型方法将整个类泛型化,那么就应该使用泛型方法。static 方法无法访问类上定义的泛型,如果 static 方法操作的引用数据类型不确定的时候,必须要将泛型定义在方法上。

4. 泛型继承的原则

假设 A 是 B 的父类
C< A > 和 C< B > 是并列关系,不具备父子类关系
A< C > 是 B< C > 的父类

5. 通配符

使用 ? 代替具体的类型参数,但 ? 是类型实参,而不是类型形参。
例如 List 在逻辑上是 List< String >,List< Integer > 等所有List<具体类型实参>的父类

通配符的错误用法

//注意点1:编译错误:不能用在泛型方法声明上,返回值类型前面<>不能使用?
public static <?> void test(ArrayList<?> list){
     }

//注意点2:编译错误:不能用在泛型类的声明上
class GenericTypeClass<?>{
     }

//注意点3:编译错误:不能用在创建对象上,右边属于创建集合对象
ArrayList<> list2 new ArrayList<?>();

受限泛型

  • 通配符指定上限:类名称 对象名称
  • 通配符指定下限:类名称 对象名称

你可能感兴趣的:(Java基础)