Java基础 -- 泛型之泛型参数

泛型机制常用的参数有3个:

“?”代表任意类型。如果只指定了<?>,而没有extends,则默认是允许任意类。

extends关键字声明了类型的上界,表示参数化的类型可能是所指定的类型,或者是此类型的子类。

super关键字声明了类型的下界,表示参数化的类型可能是所指定的类型,或者是此类型的父类型,直至Object

前提

Fruit是Apple和Orange的超类。

本章通过java代码逐一分析泛型参数的意义和区别

extends参数

public void extend(List<? extends Fruit> list, Fruit fruit){  
		Fruit now = list.get(0);  
	    System.out.println("now==>" + now);
	//    Apple a = list.get(0);  无法通过编译
	    Object o = list.get(0); 
	    System.out.println(o);
	    // list.add(fruit); //这句话无法编译    
	    // list.add(new Object());  // 无法通过编译
	    list.add(null);//这句可以编译,因为null没有类型信息  
	} 

在上面的例子中,可以明确从list中取得的记录一定是Fruit,但是无法确定是Apple,list除了传入null外,不能添加其他任何参数;分析原因前先看以下的例子:

	public void testExtendType(){
		List<? extends Fruit> list = new ArrayList<Fruit>();
		List<? extends Fruit> list2 = new ArrayList<Apple>();
		List<? extends Fruit> list3 = new ArrayList<Orange>();
		extend(list2, new Apple());
	}

从以上代码可以看出:

extends关键字声明了类型的上界,表示参数化的类型可能是所指定的类型,或者是此类型的子类, List<? extends Fruit> 可以指向 ArrayList<Fruit>()、ArrayList<Apple>()、ArrayList<Orange>()等。现在如果传入的参数list为new ArrayList<Apple>(),则此时你向此list中添加
Fruit,则肯定报错。而读取数据时,不管list是什么类型,读取的数据肯定都是Fruit,同时Fruit也是Object。

通过以上的分析,知道直接往继承extends中的列表中添加记录是不行的,那么如何向extends修饰的list中添加记录,可以使用泛型方法来达到目的:

public <T extends Fruit> void extendType2(List<T> list, T date){  
	    list.add(date);  
	} 
调用示例如下:

public void testExtendType2(){  
	    List<Apple> list = new ArrayList<Apple>();  
	    extendType2(list,new Apple());  
	}
super参数

super用的不多,只简单介绍一下。

public void superType(List<? super Apple> list, Apple apple){  
		Object o = list.get(0);
		System.out.println(o);
	//	Apple a = list.get(0); // 不能编译
		
	 // Apple apple = list.get(0); // 不能编译  
	    list.add(apple);
//	    list.add( new Object());  // 不能编译
//	    list.add( new Fruit());  // 不能编译
	}  

在以上代码中,从list中读取的记录无法确定是任何类型(除Object),list除了添加Apple外,不能添加任何类型的对象(包括Object)。分析原因前先看以下代码:

	public void testSuperType(){  
	    List<? super Apple> list = new ArrayList<Apple>();  
	    List<? super Apple> list2 = new ArrayList<Fruit>(); 
	    superType(list2, new Apple());  
	}

super关键字声明了类型的下界,表示参数化的类型是所指定的类型,或者是此类型的父类型,直至Object。List<? super Apple > 可以引用  List<Apple>,也可以引用 List<Fruit>,所以无法保证list中都是Apple,但是可以保证,所有list引用的都是Apple的父类,所有向此列表中添加Apple是没有问题的,而很显然你向List<Fruit>、List<Apple>中添加Object、Fruit对象,肯定失败,只能够添加Apple。

?参数

“?”代表任意类型。?可以看做 ? extends Object 的缩写。

	public void wideCardType(List<?> list, Fruit fruit ){
		Object o = list.get(0);
		System.out.println(list.get(0));
		//	list.add(fruit);  // 不能编译
		//	list.add(new Object()); // 不能被编译
	}

public void testWideCardType(){
		/**
		 * ? 可以看做 ? extends Object 的简化版
		 */
		List<?> list = new ArrayList<Fruit>();
		List<?> list2 = new ArrayList<Apple>();
		List<?> list3 = new ArrayList<Object>();
		
		wideCardType(list,new Fruit());
	}

List<? super Object> 可以引用  List<任何类型>,而Object是所有的对象的祖先,此list只能添加Object类型对象。

extends和super意义记忆的技巧

? extends A: ?继承A,?是A的子类,或者?是A本身
? super B:    ?是B的父类,或者?是B本身

参考文献:

http://baike.baidu.com/view/1436058.htm

http://fyting.iteye.com/blog/122732


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值