但是不能对List<? extends Shape> shapes直接进行操作:


1 import java.util.List;
2 import java.util.ArrayList;
3
4 public class Canvas{
5
//同时在画布上绘制多个形状
6
public void drawAll(List<? extends Shape> shapes){
7
for(Shape s : shapes){
8
s.draw(this);
9
}
10
}
11
12
public void addRectangle(List<? extends Shape> shapes){
13
//下面代码引起编译错误
14
shapes.add(0, new Rectangle());
15
}
16
17
public static void main(String[] args){
18
//下面的代码将会引起错误
19
//drawAll方法的形参类型是List<Shape>而不是List<Circle>
20
List<Circle> circleList = new ArrayList<>();
21
Canvas c = new Canvas();
22
//不能把List<Circle>当成List<Shape>使用
23
c.drawAll(circleList);
24
}
25 }
View Code

设定类型形参的上限:
Java泛型不仅允许在使用通配符形参时设定上限,而且还可以在定义类型形参时设定上限,用于表示给该类型形参的实际类型要么是该上限类型,要么是该上限类型的子类


1 //定义Apple类时使用了泛型声明
2 public class Apple<T extends Number>{
3
//使用T类型形参定义实例变量
4
private T info;
5
public static void main(String[] args){
6
Apple<Integer> ai = new Apple<>();
7
Apple<Double> ad = new Apple<>();
8
//下面代码将引发编译异常,下面代码试图把String类型传给T形参
9
//但String不是Number的子类型,所以引起编译错误
10
Apple<String> as = new Apple<>();
11
}
12 }
View Code

在一种极端情况下,程序需要为类型形参设定多个上限(至多有一个父类上限,可以有多个接口上限),表明该类型形参必须是其父类的子类(父类本身也可以),并且
实现了多个上限接口:


1 //表明T类型必须是Number类或其子类,并必须实现java.io.Serializable接口
2 public class Apple<T extends Number & java.io.Serializable>{
3
...
4 }
View Code
与类同时继承父类、实现接口类似,为类型形参指定多个上限时,所有接口上限必须位于类上限之后。即若需要为类型形参指定类上限,类上限必须位于第一位。
泛型方法:
Java5提供了对泛型方法的支持。
定义泛型方法格式:


1 //泛型方法,在声明方法时定义一个或多个类型形参,格式如下
2 修饰符 <T, S> 返回值类型 方法名(形参列表){
3
//方法体...
4 }
View Code
泛型方法举例:


1 static <T> void fromArrayToCollection(T[] a, Collection<T> c){
2
for(T o : a){
3
c.add(o);
4
}
5 }
View Code
泛型方法完整程序用法:


1 import java.util.Collection;
2 import java.util.ArrayList;
3
4 public class GenericMethodTest{
5
//声明一个泛型方法,该泛型方法中带一个T类型形参
6
static <T> void fromArrayToCollection(T[] a, Collection<T> c){
7
for (T o : a){
8
c.add(o);
9
}
10
}
11
12
public static void main(String[] args){
13
Object[] oa = new Object[100];
14
Collection<Object> co = new ArrayList<>();
15
//下面代码中T代表Object类型
16
fromArrayToCollection(oa, co);
17
String[] sa = new String[100];
18
Collection<String> cs = new ArrayList<>();
19
//下面代码中T代表String类型
20
fromArrayToCollection(sa, cs);
21
//下面代码中T代表Object类型
22
fromArrayToCollection(sa, co);
23
Integer[] ia = new Integer[100];
24
Float[] fa = new Float[100];
25
Number[] na = new Number[100];
26
Collection<Number> cn = new ArrayList<>();
27
//下面代码中T代表Number类型
28
fromArrayToCollection(ia, cn);
29
//下面代码中T代表Number类型
30
fromArrayToCollection(fa, cn);
31
//下面代码中T代表Number类型
32
fromArrayToCollection(na, cn);
33
//下面代码中T代表Object类型
34
fromArrayToCollection(na, co);
35
//下面代码中T代表String类型,但na是一个Number数组
36
//因为Number既不是String类型
37
//也不是它的子类,所以出现编译错误
38
fromArrayToCollection(na, cs);
39
}
40 }
View Code

数组T[]可以是其子类数组,Collection<T>只能是同类T。