一个问题
1 | List<String> l1 = new ArrayList<String>(); |
1 | 输出:true |
ok ,反正我在写这个文章之前是不懂的,可能半桶水晃得太厉害了吧!
泛型介绍
泛型:参数化类型,通俗的讲就是就是将类型作为参数传递给一个类或者方法
类型参数化
没有泛型之前
1 | private static class Test { |
1 | Test test = new Test(); |
在这里我们使用Object
来修饰 value
,这样的话,value就可以是任何类型,但是当我们get
的时候需要进行类型强转
有了泛型之后
1 | private static class Test<T> { |
1 | Test<String> test = new Test<>(); |
这里我们并没有指定Object
来修饰value,而是使用T
,当我们在初始化的时候,指定了Test<String> test = new Test<>();
.之后get
的时候就不需要进行强转操作。
但是需要注意1
2
3
4Test<String> test = new Test<>();
test.setValue("123456");
String value = test.getValue();
test.setValue(123456);//异常
最后一行语句是会报异常的,因为你在前面已经指定了value
的类型为String
,后面你设置test.setValue(123456);
就会报异常
结论:
- 当具体的类型确定后,泛型又提供了一种类型检测的机制,只有相匹配的数据才能正常的赋值,否则编译器就不通过。
- 泛型提高了程序代码的可读性,不必要等到运行的时候才去强制转换,在定义或者实例化阶段,因为 Cache
这个类型显化的效果,程序员能够一目了然猜测出代码要操作的数据类型
泛型的定义和使用
泛型的3种使用情况
- 泛型类
- 泛型方法
- 泛型接口
泛型类
泛型类定义
1 | private static class Test<T> { |
如果一个类被<T>
这种形式定义的话,那么就成这个类为泛型类
泛型类使用
Test<String> test1 = new Test<>();
泛型还可以接受多个类型参数
1 | public class Test <E,T>{ |
泛型方法
泛型方法的定义
1 | public <T> setValue(T value) { |
<T>
代表的是返回类型,T称为类型参数T value
T 称为参数化类型,不是运行时真正的参数
泛型类与泛型参数同时存在的情况
1 | public class Test1<T>{ |
Test1<T>
泛型类testMethod(T t)
普通方法<T> T testMethod1(T t)
泛型方法,以自己定义的类型参数为准
1 | Test1<String> t = new Test1(); |
泛型类的实际类型参数是String
泛型方法的实际类型参数是Integer
但是,不建议这样写
泛型接口
与泛型方法类似
通配符 ?
为什么要有通配符 ?
1 | class Father{} |
1 | List<Son> sonList = new ArrayList<>(); |
上面的代码编译器不通过
通配符测出现就是为了制定泛型中的类型范围
通配符的三种形式:
<?>
被称作无限定的通配符<? extends T>
被称作有上限的通配符<? super T>
被称作有下限的通配符
无限定通配符
1 | public void setValue(Collection<?> collection) { |
<?>
只提供了只读功能,只具备与具体类型无关的能力
有上限的通配符
1 | public void setValue(Collection<? extends Base> collection) { |
这里我们知道collection
的类型Collection
接受Base
以及Base
的子类
有下限的通配符
1 | public void setValue(Collection<? super Son> collection) { |
用通配符做的事情,都可以采用类型参数代替
类型擦除
泛型信息只存在于代码编译阶段,在进入 JVM
之前,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除
1 | public static void main(String[] args) { |
输出1
2
3
4java.util.ArrayList
java.util.ArrayList
类型擦除之后都是 java.util.ArrayList
true
在泛型类被类型擦除的时候,之前泛型类中的类型参数部分如果没有指定上限,如
注意
1 | List<Integer>[] li2 = new ArrayList<Integer>[10];//报错 |
Java 不能创建具体类型的泛型数组
1 | Listnew ArrayList >[10]; >[] li2 = |