泛型问题

[TOC]

1. 概述

泛型指的是可以将类型作为参数进行传递,其本质上就是类型参数化。比如:我们平时定义一个方法的时候,常会指定要传入一个具体类对象作为参数。而如果使用泛型,那么这个具体传入类的对象,就可以指定为某个类型,而不必指定具体的类。也就是我们将某个类型作为参数进行传递了。

1
2
3
4
//普通方法
public void testValue(String s) {}
//泛型方法
public <T> void testValue(T t) {}

2. 使用泛型有哪些好处?

  • 它可以避免类型强制转换,而引起的程序异常。
  • 可以是代码更加简洁易度。

3. 类型擦除

泛型值存在于编译期,代码在进入虚拟机后泛型就会会被擦除掉,这个者特性就叫做类型擦除。当泛型被擦除后,他有两种转换方式,第一种是如果泛型没有设置类型上限,那么将泛型转化成Object类型,第二种是如果设置了类型上限,那么将泛型转化成他的类型上限。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//未指定上限
public class Test1<T> {
T t;
public T getValue() {
return t;
}
public void setVale(T t) {
this.t = t;
}
}
//指定上限
public class Test2<T extends String> {
T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
//通过反射调用获取他们的属性类型
@Test
public void testType1() {
Test1<String> test1 = new Test1<>();
test1.setVale("11111");
Class<? extends Test1> aClass = test1.getClass();
for (Field field : aClass.getDeclaredFields()) {
System.out.println("Test1属性:" + field.getName() + "的类型为:" + field.getType().getName());
}

Test2 test2 = new Test2();
test2.setT("2222");
Class<? extends Test2> aClass2 = test2.getClass();
for (Field field : aClass2.getDeclaredFields()) {
System.out.println("test2属性:" + field.getName() + "的类型为:" + field.getType().getName());
}
}
复制代码

上面方法打印的结果:

1
2
Test1属性:t的类型为:java.lang.Object
Test2属性:t的类型为:java.lang.String

4.泛型的两个关键字?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class test {
public static void main(String[] args){
List<? extends A> list1 = new ArrayList<A>();
// list1.add(new A()); //错误,编译器无法确定List所持有的类型,所以无法安全的向其中添加对象
A a = list1.get(0);
List<? extends A> list2 = new ArrayList<B>();
List<? super B> list3 = new ArrayList<B>();
list3.add(new B());
//想要正确,必须向下转型,但是向下转型是不安全的,非常容易出错
// B b = list3.get(0); //编译器无法确定get返回的对象类型是B,还是B的父类或 Object.

}
static class A{}
static class B extends A {}
}

ArrayList heroList<? extends Hero> 表示这是一个Hero泛型或者其子类泛型
heroList 的泛型可能是Hero
heroList 的泛型可能是APHero
heroList 的泛型可能是ADHero
所以 可以确凿的是,从heroList取出来的对象,一定是可以转型成Hero的

但是,不能往里面放东西,因为
放APHero就不满足
放ADHero又不满足

ArrayList heroList<? super Hero> 表示这是一个Hero泛型或者其父类泛型
heroList的泛型可能是Hero
heroList的泛型可能是Object

可以往里面插入Hero以及Hero的子类
但是取出来有风险,因为不确定取出来是Hero还是Object