您的位置:首页 > 编程语言 > Java开发

浅析java的泛型通配符

2013-05-28 14:49 246 查看
import java.util.ArrayList;

import java.util.List;

public class TestGeneric {

public static void main(String[] args) {

List<? extends Fruit> list1 = new ArrayList<Apple>();

//list.add(new Fruit());

//list.add(new Apple());

/*

*

* 上面的两句都是不正确的,为什么呢?首先为什么要List<? extends Fruit> = new ArrayList<Apple>();这样写呢?

这样写的目的无非是想利用一下,抽象的基类来表示子类(也就是父类引用指向子类对象)。但是这里需要注意的一个问题就是,

java的泛型机制是通过它的编译系统来完成的(其实,数组和泛型容器在这里的区别很大,见下面的例子)。List<? extends Fruit>告诉编译器:"我是一个可以装载某个具体的Fruit的子类的List容器"。

而=new ArrayList<apple>();则指明了这个list装载的实际上是Apple类型。那为什么list.add(new Apple())通不过编译呢?因为编译器只是

知道list可以装载某个Fruit的子类,但是它也不知道具体是那种。

其实上面的机制主要是为了保证java运行时的安全性。试想,如果你定义了List<? extends Fruit> list = new ArrayList<Apple>();

而list.add(new 任何Fruit的子类)可以通过编译的话,那么你的list就有可能装入了Banana类型,这样就与你的初衷 ArrayList<Apple>矛盾了

这样泛型的安全性就保证不了了。

<? extends Fruit>表示的是Fruit或者任何Fruit的子类,其中Fruit最大。<? super Fruit> 表示Fruit和任何Fruit的父类,

Fruit最小,这样的话,用List<? super Fruit>来声明的话,就可以任意的add Fruit的子类了,因为它肯定是你运行时对象的子类,这样并不破坏

泛型机制的装载安全性。

List<? super Banana> list2 = new ArrayList<Banana>();

list2.add(Banana);

list2.add(SmallBanana);

list2.add(BigBanana);

以上的写法都是可以的

*

*

*/

//Banana[] b = new BigBanana[10];

//List<Banana> list2 = new ArrayList<BigBanana>();

/*

* 上面的两个例子,b可以通过编译,但是list2没有,为什么?其实还是为了保证安全性(数组是不保证的,如果b[0]=new SmallBanana(),编译不报错,运行时候会报错ArrayStore),可能不慎引入

* Banana的子类但不是BigBanana类型。这样在编译的时候就保证了安全性。

*

*/

}

}

class Fruit{

}

class Apple extends Fruit{

}

class Banana extends Fruit{

}

class BigBanana extends Banana{

public String toString() {

return "I am a BigBanana";

}

}

class SmallBanana extends Banana{

public String toString() {

return "I am a SmallBanana";

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  泛型 通配符