5.26-5.29 使用泛型

以下类使用了泛型:

public class Container <E>{
	private List<E> elements=new ArrayList<E>();
	
	public void addAll(List<E> list){
		elements.addAll(list);
	}
	
	public void removeAll(List<E> list){
		list.addAll(elements);
		elements.clear();
	}
	
	public static <T> List<T> union(List<? extends T> list1,List<? extends T> list2){
		return null;
	}
}

 

使用以下测试代码将报错:

		List<Integer> list1=Arrays.asList(1,2,3);
		
		Container<Number> container=new Container<Number>();
		container.addAll(list1);//编译时报错

 

以上测试代码,因为使用了Container<Number>声明,addAll()将仅接受List<Number>类型的参数值,所以当传入一个List<Integer>类型的参数将报错,尽管Integer是Number的子类

 

可以使用泛型通配符增加泛型方法的适应性,其基本原则为PECS(producer-extends,consumer-super),以上例,addAll()传入的list参数将提供数据给container对象,所以此list对象相对container来说是producer。同理,removeAll()传入的list参数将使用container移除的对象,所以此list是consumer。根据以上原则,修改方法如下:

	public void addAll(List<? extends E> list){
		elements.addAll(list);
	}
	
	public void removeAll(List<? super E> list){
		list.addAll(elements);
		elements.clear();
	}

 

所有Comparable、Comparator都是Consumer,在使用此接口时应使用如下声明:

	public <T extends Comparable<? super T>> T max(List<T> list){
		return null;
	} 

 

以下测试union()的代码将报错,传入的参数分别是List<Integer>, List<Double>类型,导致编译器不知道应使用哪种参数类型(为什么编译器不从返回结果的类型List<Number>获取实际参数类型?)

		List<Integer> list1=Arrays.asList(1,2,3);
		List<Double> list2=Arrays.asList(4.0d,5.0d,6.0d);
		
		List<Number> list=Container.union(list1, list2);//编译时报错

 

可以进行如下修改,显式指定编译器使用的实际参数类型为Number:

List<Number> list=Container.<Number>union(list1, list2);

 

 使用泛型可以限制“容器”所能存储的元素的类型,如List<E>的限制容器List里仅能存放类型为E的元素。对应类似Map类型的容器,可以对key使用泛型,如下接口key的类型为Class<T>,而value为T,即value.class类型与key相同,这称为typesafe heterogeneous container:

注:可以调用Class.asSubclass() 进行类型转换

public class Favorites {
	public <T> void putFavorite(Class<T> type, T instance);

	public <T> T getFavorite(Class<T> type);
}

 

具体实现类:

public class Favorites {
	private Map<Class<?>, Object> favorites = new HashMap<Class<?>, Object>();

	public <T> void putFavorite(Class<T> type, T instance) {
		if (type == null)
			throw new NullPointerException("Type is null");
		favorites.put(type, type.cast(instance));//避免放入与type类型不同的对象
	}

	public <T> T getFavorite(Class<T> type) {
		return type.cast(favorites.get(type));
	}
}

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(泛型)