为什么使用泛型?
- Java编译器在编译时加强泛型代码的类型检查,避免运行时不可预料的错误。
- 泛型支持程序化类型作为参数,使方法兼具灵活性。
- 泛型能让你实现泛型算法,更具有通用性。
泛型类型和方法
- 泛型类型
参数化类型的类或接口。
格式:class name { /* ... */ },其中T1,T2称为type parameters。
调用泛型类型(又称为参数化类型):Box integerBox,传入具体的类型。
实例化泛型类型:Box integerBox = new Box();
- 泛型方法
参数化类型的方法。
格式:public static boolean compare(Pair p1, Pair p2),static,non-static均可。
调用泛型方法:Util.compare(p1, p2)。可以利用类型推断,像调用普通方法一样调用泛型方法,如:Util.compare(p1, p2)
- 通过extends来限定泛型类型和方法的边界
通配符和子类型
- Integer是Number的子类,但参数化类型Box和Box没有关系,他们的共同父类是Object。
![915ae0cc4deedefd0b87ef5342ae6c50.gif](https://i-blog.csdnimg.cn/blog_migrate/059bbd3faec3838553aa0a4ab5c70188.gif)
- 泛型类型之间几乎没有关系,但可以通过通配符在泛型类型之间建立关系。
![178b7c61062d5b47d0fe10cb20d246ce.gif](https://i-blog.csdnimg.cn/blog_migrate/6c38d4699a802b14c980db32b515a2c9.gif)
- ?通配符,用于参数、字段、局部变量的类型,不用于泛型类型和方法。
上界:List extends Number>,不确定类型是指定类型或指定类型的子类,可以放松对变量的限制,如匹配List,List。例如,List仅匹配Number类型的List,而List extends Number>匹配Number类型和其子类的List。
无界:List>,不确定类型的List。使用场景:1)List的元素都是Object类型,直接可以使用Object的方法。2)泛型类中的方法不依赖于类型参数。
下界:List super Integer>,不确定类型是指定类型或指定类型的父类,可以尽量提高灵活性,如匹配List,List,List。
- 通配符使用的场景
把参数变量看作两类:
1、『in』提供给方法内部使用,即传入数据。
2、『out』提供给方法外部使用,即传出数据。
利用Wildcard Capture特性,通配符使用的场景为:
1、『in』使用上界通配符
2、『out』使用下界通配符
3、『in』可以使用Object的方法,使用无界通配符
4、即用作『in』,又用作『out』的,不使用通配符
泛型的限制
- 不能用primitive类型实例化泛型。如:Pair p = new Pair<>(8, 'a');
- 不能实例化参数类型。如:new E();
- 不能定义类的静态类型字段是参数类型。如:private static T os;
- 参数类型不能使用instanceof和类型转换。如:list instanceof ArrayList
- 不能创建参数化类型数组。如:List[] arrayOfLists = new List[2];
- 不能Create, Catch, 或者 Throw 参数化类型对象。如:class MathException extends Exception { /* ... */ }
- 重载方法不能使用参数化类型被擦除后拥有同样的原生类型。如:
public void print(Set strSet) { }
public void print(Set intSet) { }
被编译擦除后是一样的public void print(Set strSet) { }