但是这种带通配符的List仅表示它是各种泛型List的父类,并不能把元素加入到其中。如下面代码会引起错误:
1 import java.util.List; 2 import java.util.ArrayList; 3 4 public class GeneicTest1{ 5 public static void main(String[] args){ 6 List<?> list = new ArrayList<String>(); 7 list.add("疯狂Java讲义"); 8 } 9 } View Code设定类型通配符的上限:
当直接使用List<?>这种形式,即表明这个List集合可以是任何泛型List的父类。但还有一种特殊的情形,程序不希望这个List<?>是任何泛型List父类,只希望它代表某一类
泛型List的父类:
1 //定义一个抽象类Shape 2 public abstract class Shape{ 3 public abstract void draw(Canvas c); 4 } View Code 1 //定义Shape的子类Circle 2 public class Circle extends Shape{ 3 //实现画图方法,以打印字符串来模拟画图方法实现 4 public void draw(Canvas c){ 5 System.out.println("在画布" + c + "上画个圆"); 6 } 7 } View Code 1 //定义Shape的子类Rectangle 2 public class Rectangle extends Shape{ 3 public void draw(Canvas c){ 4 //实现画图方法,以打印字符串来模拟画图方法实现 5 System.out.println("把一个矩形画在画布" + c + "上"); 6 } 7 } View Code View Code上面的错误关键在于List<Circle>并不是List<Shape>的子类,所以不能把List<Circle>对象当成List<Shape>使用。为了表示List<Circle>的父类,可以考虑使用List<?>:
1 import java.util.List; 2 import java.util.ArrayList; 3 4 public class Canvas{ 5 //同时在画布上绘制多个形状 6 public void drawAll(List<?> shapes){ 7 for(Object obj : shapes){ 8 Shape s = (Shape) obj; 9 s.draw(this); 10 } 11 } 12 13 public static void main(String[] args){ 14 //下面的代码将会引起错误 15 //drawAll方法的形参类型是List<Shape>而不是List<Circle> 16 List<Circle> circleList = new ArrayList<>(); 17 Canvas c = new Canvas(); 18 //不能把List<Circle>当成List<Shape>使用 19 c.drawAll(circleList); 20 } 21 } View Code上面程序使用了通配符来表示所有的类型。问题是上面的方法实现体显得非常臃肿且繁琐:使用了泛型还需要强制类型转换。
实际上需要一种泛型表示方法,它可以表示所有Shape泛型List的父类,即List<?>可以匹配所有Shape和Shape的子类的List集合,而不用使用强制类型转换。
Java为泛型提供了被限制的泛型通配符。被限制的通配符表示如下:
//它表示所有Shape泛型List的父类
List<? extends Shape>
有了这种被限制的泛型通配符,把上面的Canvas程序改成如下:
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 static void main(String[] args){ 13 //下面的代码将会引起错误 14 //drawAll方法的形参类型是List<Shape>而不是List<Circle> 15 List<Circle> circleList = new ArrayList<>(); 16 Canvas c = new Canvas(); 17 //不能把List<Circle>当成List<Shape>使用 18 c.drawAll(circleList); 19 } 20 } View CodeList<? extends Shape>:意思是List<>尖括号中只要是Shape或Shape的子类都可以。