泛型

泛型在集合、比较器中的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//泛型在List中的使用
@Test
public void test1(){
//举例:将学生成绩保存在ArrayList中
//标准写法:
//ArrayList<Integer> list = new ArrayList<Integer>();
//jdk7的新特性:类型推断
ArrayList<Integer> list = new ArrayList<>();

list.add(56); //自动装箱
list.add(76);
list.add(88);
list.add(89);
//当添加非Integer类型数据时,编译不通过
//list.add("Tom");//编译报错

Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()){
//不需要强转,直接可以获取添加时的元素的数据类型
Integer score = iterator.next();
System.out.println(score);
}
}
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
//泛型在Map中的使用
@Test
public void test2(){
HashMap<String,Integer> map = new HashMap<>();

map.put("Tom",67);
map.put("Jim",56);
map.put("Rose",88);
//编译不通过
// map.put(67,"Jack");

//遍历key集
Set<String> keySet = map.keySet();
for(String str:keySet){
System.out.println(str);
}

//遍历value集
Collection<Integer> values = map.values();
Iterator<Integer> iterator = values.iterator();
while(iterator.hasNext()){
Integer value = iterator.next();
System.out.println(value);
}

//遍历entry集
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
Iterator<Map.Entry<String, Integer>> iterator1 = entrySet.iterator();
while(iterator1.hasNext()){
Map.Entry<String, Integer> entry = iterator1.next();
String key = entry.getKey();
Integer value = entry.getValue();
System.out.println(key + ":" + value);
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class CircleComparator1 implements Comparator<Circle> {

@Override
public int compare(Circle o1, Circle o2) {
//不再需要强制类型转换,代码更简洁
return Double.compare(o1.getRadius(), o2.getRadius());
}
}

//测试类
public class TestHasGeneric {
public static void main(String[] args) {
CircleComparator1 com = new CircleComparator1();
System.out.println(com.compare(new Circle(1), new Circle(2)));

//System.out.println(com.compare("圆1", "圆2"));
//编译错误,因为"圆1", "圆2"不是Circle类型,是String类型,编译器提前报错,
//而不是冒着风险在运行时再报错。
}
}
  • 在创建集合对象的时候,可以指明泛型的类型。

    具体格式为:List list = new ArrayList();

  • JDK7.0时,有新特性,可以简写为:

    List list = new ArrayList<>(); //类型推断

  • 泛型,也称为泛型参数,即参数的类型,只能使用引用数据类型进行赋值。(不能使用基本数据类型,可以使用包装类替换)

  • 集合声明时,声明泛型参数。在使用集合时,可以具体指明泛型的类型。一旦指明,类或接口内部,凡是使用泛型参数的位置,都指定为具体的参数类型。如果没有指明的话,看做是Object类型。

自定义泛型

  • 声明类或接口时,在类名或接口名后面声明泛型类型,我们把这样的类或接口称为泛型类泛型接口
1
2
3
4
5
6
7
8
9
10
11
12
[修饰符] class 类名<类型变量列表> [extends 父类] [implements 接口名]{

}
[修饰符] interface 接口名<类型变量列表> [implements 接口名]{

}

//例如:
public class ArrayList<E>
public interface Map<K,V>{
....
}
  • 声明方法时,在【修饰符】与返回值类型之间声明类型变量,我们把声明了类型变量的方法,称为泛型方法。
1
2
3
4
5
6
7
8
[修饰符] <类型变量列表> 返回值类型 方法名([形参列表])[throws 异常列表]{
//...
}

//例如:java.util.Arrays类中的
public static <T> List<T> asList(T... a){
...
}

泛型在继承上的体现

继承必须要泛型一致才算。

下面代码就是想表达这个意思

1
2
3
4
5
6
7
8
        //泛型不同
ArrayList<Object> list = null;
ArrayList<String> list1 = null;
// list=list1;//编译不通过
//泛型相同
List<String> list2 = null;
ArrayList<String> list3 = null;
list2 = list3;//编译通过

通配符

通配符的使用

1
2
3
4
5
6
7
8
@Test
public void test2(){
ArrayList<?> list = null;
ArrayList<Object> list1 = null;
ArrayList<String> list2 = null;
list = list1;//编译通过
list = list2;//编译通过
}

有通配符的泛型的读写:

1
2
3
4
5
6
7
8
9
10
11
@Test
public void test3(){
ArrayList<?> list = null;
ArrayList<String> list2 = new ArrayList();
list2.add("123");
list = list2;
//允许读取,读取的值的类型为Object类型
Object object = list.get(0);
//不允许写入(除了null)
list.add(null);
}

有限制条件的通配符

1
2
3
4
5
<? extends Number>     //(无穷小 , Number]
//只允许泛型为Number及Number子类的引用调用

<? super Number> //[Number , 无穷大)
//只允许泛型为Number及Number父类的引用调用