Java泛型

1 概念

JDK1.5中引入了泛型的的概念,泛型的本质是“参数化类型”,在类型参数在使用(如继承或实现接口)时确定。

泛型可以在编译期进行类型安全检测。

Java泛型是在编译器这个层次实现的,字节码中是不包含泛型中的类型信息的。编译器在编译时去掉泛型,称为类型擦除。

2 泛型方法

泛型方法的格式为在方法的修饰符后面添加泛型标记<E>,使得方法被调用时可以接收不同类型的参数。

public static <E> List<E> arrayToList(E[] arr) {
    ArrayList<E> list = new ArrayList<>();
    for (E e : arr) {
        list.add(e);
    }
    return list;
}

注意:

  • 泛型方法可以在任何类中使用,在泛型类中使用时,泛型方法的泛型参数E和泛型类的T是没有关系的。
  • 泛型方法可以声明为static方法,因为泛型参数是在调用该方法时确定的,不是在实例化类时确定的。

3 泛型类

在类名后面添加泛型参数的声明<T>.

  • 泛型参数可以作为非静态属性的类型,非静态方法的参数类型,非静态方法的返回值类型,但在静态方法中不能使用类的泛型
    原因:静态方法在类加载的准备阶段就完成,而泛型参数的确定是在实例化对象的时候。
  • 不能使用new T[len],可以使用T[] arr = (T[]) new Object[len];

4 类型通配符

  • ?可以替代具体的参数类型,逻辑上 List<?>是所有List<具体类型参数>的父类。
  • <? extends T>表示该通配符只能匹配T以及它的子类
  • <? super T>表示该通配符只能匹配T 和它的父类

主要特点:

  • <? extends T>属于 get first, 主要用于查看数据,如 List<? extends T>类型的对象如果使用 add(T e)方法,编译期报错,因为赋值操作后,集合中并没有限定泛型的类型,而是通过<capture#1-of ? extends T>占位符表示捕获了一个 T 或 T 的子类,具体类型未知,所以不能使用 add()

  • <? super T> 属于 put first, 主要用于频繁加入数据的场景,也可以用于获取数据,但需要强制类型转换(默认返回 Object 类型)

class Animal {}
class Cat extends Animal {}
class Garfield extends Cat {}

public class Test {
	public static void main(String[] args) {
		// 基本的 List 集合
		List<Animal> animals = new ArrayList<>();
        List<Cat> cats = new ArrayList<>();
        List<Garfield> garfields = new ArrayList<>();

		// 简单添加数据
		animals.add(new Animal());
        cats.add(new Cat());
        garfields.add(new Garfield());

		//  ? extends T 类型通配符
		List<? extends Cat> extendsCatFromCat = cats;
		
		// get 操作正常,且返回类型为 T 满足多态
		Cat cat = extendsCatFromCat.get(0);
		// add() 编译错误
        extendsCatFromCat.add(new Cat());

		// ? super T 类型通配符
		List<? super Cat> superCatFromCat = cats;
		// 正常添加数据,必须是 Cat 或 Cat子类
		superCatFromCat.add(new Cat());
        superCatFromCat.add(new Garfield());
        // get 要强制类型转换
        Cat c = (Cat) superCatFromCat.get(2);
	}
}
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页