*浅谈Java中的泛型 * <Excerpt in index | 首页摘要>
Java中的泛型、泛型类、泛型方法
<The rest of contents | 余下全文>
泛型
为什么使用泛型
- 存储在集合中的元素,取出来都是Object类型的,此时就得强转
- 约束存储到集合中的元素必须是相同的数据类型
- 设计一个点类,来封装坐标位置,要求坐标位置支持String支持integer支持double类型(重复设计)
泛型(Generic Type)
从Java5开始支持的新语法
什么是泛型
- 广泛通用的类型
- 代码模板中类型不确定,谁调用该段代码,谁指明类型
简单定义
1 | class Demo<T>{ |
泛型类
直接在类/接口上定义的类型
泛型类的子类继承泛型类是需要指定类型
使用泛型:保证前后类型一致
1 | List<String> list = new ArrayList<String>(); |
因为前后类型相同,所以Java7开始,推出了泛型的菱形语法<>
1 | List<String> list = new ArrayList<>(); |
泛型不存在继承的关系,例如:
1 | List<Object>list = new ArrayList<String>();//错误的 |
从此以后,使用集合都得使用泛型来约束该集合中的元素的类型
通过反编译发现:泛型也是语法糖,底层依然使用强制类型转换的方式实现
泛型方法
在方法上声明泛型
- 泛型类中的泛型只能适用于非静态方法,如果需要给静态方法设置泛型,此时使用泛型方法
- 泛型类中的泛型应该适用于整个类中的多个方法,有时候支队某一个方法设置泛型即可
一般的,把自定义的泛型作为该方法的返回类型才有意义,而且此时的泛型必须是由参数设置进来的,如果没有参数来设置泛型的具体类型,此时的方法一般返回设计为Object即可
代码示例
1 | //表示在该方法中使用T来表示一种未知类型 |
泛型的通配符、上限和下限
泛型的通配符:不知道用什么类型来接收时,此时可以使用?,?表示未知通配符
1
2
3
4
5
6
7
8public class Demo{
public static void main(String[]args){
}
private static void function(List<?>list){
//此时只能接收数据,不能添加数据至list
}
}泛型的上限和下限:用来限定元素的类型必须时X类的子类或相同,X类的父类或相同
1
2
3
4
5
6
7
8//泛型的上限:此时的泛型?必须时Numer类型或Number类的子类
public static void function(List<? extends Number> list){
}
//泛型的下限:此时的泛型?必须时Number类型或Number类的父类
public static void function(List<? super Number>list){
}
泛型的擦除和转换
泛型的擦除:
泛型编译之后就消失了(泛型的自动擦除)
当把带有泛型的集合赋给不带泛型的集合,此时泛型被擦除(手动擦除)
1
2
3
4
5
6
7
8public class Demo{
public static void main(String[]args){
List<Integer> list1 = new ArrayList<>();
list1.add(1);
List list2 = null;
list2 = list1;//此时泛型擦除
}
}
堆污染:
当一个方法既使用泛型的时候也使用可变参数,此时容易导致堆污染问题。
如:在Arrays类中的 asList() 方法