泛型笔记
一、概念
泛型提供了编译时类型安全监测机制,该机制允许我们在编译时检测到非法的类型数据结构。本质上就是参数化类型,也就是所操作的数据类型被指定为一个参数。
优点:类型安全、消除了强制类型的转换、一定程度上的代码复用。
泛型类型不能够用继承来理解
二、泛型类
常用的泛型标识:T、E、K、V (K V一般作为键值对结合使用)
-
泛型类在创建对象的时候,指定操作的具体数据类型。
-
如果泛型类在创建对象的时候没有指定类型,将按照Object类型来操作。
-
泛型类不支持基本数据类型。
-
同一泛型类,根据不同的数据类型创建的对象,本质上是同一类型(this.class)。
-
带有类中泛型类型的方法,不可被声明为static
三、泛型类派生子类
子类也是泛型类,子类和父类的泛型类型要一致。即使子类泛型类型有扩展,也要保证有一个类型和父类一致
class ChildGeneric<T> extends Generic<T>
子类不是泛型类,继承时父类要明确泛型的数据类型
class ChildGeneric extends Generic<String>
四、泛型接口
实现类不是泛型类,接口要明确数据类型
public class Apple implements Generator<String>
实现类也是泛型类,实现类和接口的泛型类型要一致。即使子类泛型类型有扩展,也要保证有一个类型和接口类一致
public class Pair<T,E> implements Generator<T>
五、泛型方法
泛型类,是在实例化类的时候指明泛型的具体类型
泛型方法,是在调用方法的时候指明泛型的具体类型,泛型方法中的泛型类型与类中的泛型类型相互独立
-
public与方法返回值中间的泛型列表<T>非常重要,可以理解为声明此方法为泛型方法。
-
只有声明了泛型列表的方法才是泛型方法,泛型类中使用了泛型的成员方法并不是泛型方法。
-
泛型列表<T>表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。
-
与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。
public <T,E,...> 返回值类型 方法名(形参列表){
方法体...
}
泛型方法可变参数
可以传入多个相同类型的参数
public <E> void print(E... e){
for (E e1 : e){
System.out.println(e);
}
}
六、类型通配符
类型通配符一般是使用 “ ? ”代替具体的类型实参
所以,类型通配符是类型实参,而不是类型形参
public void test(Box<?> box){}
类型通配符的上限
类/接口<? extends 实参类型>
要求该泛型的类型,只能是实参类型,或实参类型的子类类型
类型通配符的下限
类/接口<? super 实参类型>
要求该泛型的类型,只能是实参类型或实参类型的父类类型。此种方式的形参方法,不保证约束要求;参数要用Object类型去接收
七、类型擦除
泛型是java1.5版本引进的概念,但是,泛型代码能够很好地和之前版本的代码兼容。那是因为,泛型信息只存在于代码编译阶段,在进入JVM之前,与泛型相关的信息会被擦除掉,我们称之为——类型擦除。




八、泛型数组
可以声明带泛型的数组引用,但是不能直接创建带泛型的数组对象。
泛型在编译期会做类型擦除,而数组会在整个编译器一直持有类型,会产生冲突
public class generic {
public static void main(String[] args) {
List<String>[] list1 = new ArrayList<String>[5]; //×
List<String>[] list2 = new ArrayList[5]; //√
}
}
可以通过java.lang.reflect.Array的new Instance(Class<T>,int)创建 T[] 数组
Array.newInstance(class,length)
尽量不要采用泛型数组,而是采用泛型集合代替泛型数组

浙公网安备 33010602011771号