泛型
1. 泛型入门
1)Java的参数化类型被称为泛型,就是将类型当作参数一样在编译时确定。允许在定义类、接口、方法时使用 类型形参,这个类型形参创建对象、调用方法时动态指定。其保证只要在编译时没有发出警告,运行时就不 会有ClassCastException异常。
2)菱形语法:允许在构造器后不需要带完整的泛型信息只要给出一对<>就行,java可以推断出尖括号里应该是 什么泛型信息。
3)类型形参在整个接口、类体内可当成类型使用,几乎所有可以使用普通类型的地方都可以使用,但是在静态方 法、初始化块或者静态变量的声明和初始化时不能使用泛型,因为并不存在泛型类。 泛型在使用时传入的 类型实参不可以是基本数据类型。
4)List和List<E>是不同的数据类型,可以将后者看做前者的子类,但是包含泛型声明的类型可以在定义变量、 创建对象是传入一个类型实参,从而可以动态的生成无数个逻辑上的子类,但这些子类在物理上并不存在 并不存在泛型类,故instanceof后面不能使用泛型类型。
5)当为带有泛型的接口、父类创建实现类或子类时必需要类型实参化,因为定义不用类型实参化但使用必须要 类型实参化。就和方法的数据形参一样,调用方法时必须传入实参。因此如果重写父类的方法时就要注意。
2.类型通配符
1)类型通配符是一个?号,将一个问号作为类型实参传给一个List集合(假设)写作List<?>-意思是类型未知的List 它的元素类型可以匹配任何类型,相当于Object类型。它代表各种泛型的父类但是并不能把元素加入其中, null除外。
2)类型通配符上限<? extends RootClass>:此处的未知类型一定是RootClass的子类型也可以是RootClass本身 这里的RootClass是通配符?的上限。
类型通配符下限<? super RootClass>:此处的未知类型一定是RootClass的父类型也可以是RootClass本身, 这里的RootClass是通配符?的下限。
通配符的上限与下限有个重要区别:下限是可以添加集合元素的,而上限不可以也就是下限类型是确定的。
3)类型形参上限<T extends RootClass>:用于表示传递给此类型形参的实际类型要么是该上限类型RootClass要 么是该上限类型的子类。为类型形参设定多个上限时最多有一个父类,可以有很多接口但排列顺序是类在 前接口在后,而且要用&符号连接。
3.泛型方法
1)泛型方法就是在声明方法时定义一个或多个类型形参,类型形参用<>括起来并且放在方法的修饰与返回值之 前,多个形参之间用逗号隔开。
2)方法中类型形参只能在方法中使用,方法中的泛型形参不必显式传入实际类型,java编译器会根据实参推断 类型形参的值。
3)泛型方法和类型通配符的区别:大部分时候都可以用泛型方法来代替类型通配符。
泛型方法:用来表示方法的一个或多个参数之间的类型依赖关系,或者方法返回值与参数之间的类 型依赖关系。如果没有这样的依赖关系则不应该使用泛型方法。
通配符:是被设计用来支持灵活的子类化的。类型通配符即可以在方法签名中定义形参的类型,也可以定义 变量的类型,但泛型方法中的类型形参必须在在对应方法中显式声明。
4)泛型构造器:在构造器签名中声明类型形参这就是泛型构造器,调用泛型构造器时既可以让编译器推断也可 以指定实际形参,但如果指定了实际类型形参就不可以用菱形语法。
4.搽除与转换
1)搽除:如果没有为泛型类指定实际的类型参数,则这个类型参数被称作raw type,默认是声明该类型参数时指定的第一个上限类型。List<Type>和List对象之间是可以赋值的。这种情况就会存在搽除,而且可能会引起异常。