您的位置:首页 > 其它

14、泛型类、接口,和类型通配符

2015-03-26 12:13 295 查看
在定义类和接口时,可以传入泛型参数(类型形参),用尖括号

public interface Map< K, V>


显然,K和V只能用来做声明对象之类的动作,调用方法是不可能的。

在方法的参数中,也可以使用泛型,但是跟定义类和接口时不一样,不能使用尖括号加任意形参的形式

public void drawAll(List<T> shapes)
{

}


即使没有使用T,上面代码也是错误的,不能通过编译,如下形式是正确的:

class Canvas
{
public void drawAll(List<Shape> shapes)
{
for(Shape s : shapes)
{
s.draw(this);
}
}
}


Circle是Shape的一个子类,但是List<Circle>不是List<Shape>的子类,所以List<Circle>不能作为drawAll方法的参数,如下代码会引起编译错误

List<Circle> circleList = new ArrayList<>();
Canvas c = new Canvas();
c.drawAll(circleList);//此行错误


在方法的参数列表中,可以使用带类型通配符的泛型

class Canvas
{
public void drawAll(List<?> shapes)
{
for(Object obj : shapes)
{
Shape s = (Shape)obj;
s.draw(this);
}
}
}
问号“?”表示各种类的父类,此处没有限定,则表示Object类,所以使用时要强制转换。通配符即表明类型未知且可变,所以这样带通配符(不管有没有限定)声明一个List是不能往里面添加元素的。

<pre name="code" class="java">List<?> lc = new ArrayList<String>();//或者<span style="font-family: Arial, Helvetica, sans-serif;">List<? extends xxxx> lc = new ArrayList<String>()</span>
lc.add(new String());

lc.add(new Object());
上面的后两行都会引起编译错误。

在方法的参数中,?通配符过于麻烦(需强制转换)且不安全(各种类型皆可传入)。可以使用带限制的类型通配符

class Canvas
{
public void drawAll(List<? extends Shape> shapes)
{
for(Shape s : shapes)
{
s.draw(this);
}
}
}
这样一来,只需要List<?>中的?继承自Shape即可,也可以是Shape自身,Shape被称为这个通配符的上限。Shape本身是一个抽象类,draw是一个抽象方法,传入不同的List<?>,就会调用不同的draw,这也正是利用了多态性。

同样的,在定义类和接口时使用泛型,也可以设定类型形参的上限,例如:

public interface Map< K extends T, V>
此时K声明的对象就可以使用T的方法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐