十八、泛型详解

一、基础增强

1. 课程回顾
 
		XML技术
		Servlet/Jsp
		数据库
		Jdbc技术
		JavaWeb增强
			过滤器、监听器、文件上传与下载、国际化
		
		学过的组件:
			Dom4J/Xpath、DBUtils、C3p0、BeanUtils、log4J…
		    Struts  /  Spring   /  Hibernate
		

二、泛型

2.1 泛型的基本概念

2.2.1 什么是泛型
 	 泛型是JDK1.5以后才有的, 可以在编译时期进行类型检查,且可以避免频繁类型
 	 转化!
2.2.2 泛型的作用
		泛型可以把运行时异常提前至编译时异常。
		
	
	// 运行时期异常 
	@Test
	public void testGeneric() throws Exception {
		// 集合的声明
		List list = new ArrayList();
		list.add("China");
		list.add(1);
		
		// 集合的使用
		String str = (String) list.get(1);
		
	}
	
	// 使用泛型
	@Test
	public void testGeneric2() throws Exception {
		// 声明泛型集合的时候指定元素的类型
		List<String> list = new ArrayList<String>();
		list.add("China");
//		list.add(1);// 编译时期报错
		
		String str = list.get(1); 
	}

2.2.3 泛型擦除
	泛型只在编译时期有效,编译后的字节码文件中不存在有泛型信息!·
	下面的代码会报错,原因是:泛型编译后会进行擦除。
	
	/*
	 * 泛型擦除实例 
	 */
	public void save(List<Person> p){
		...
	}
	public void save(List<Dept> d){    // 报错: 与上面方法编译后一样
		...
	}

2.2 泛型写法

		1.泛型必须是引用类型,不是基本类型
		2.前后两端泛型必须一致。
		3.一端出现泛型即可。
	// 泛型写法
	@Test
	public void testGeneric3() throws Exception {
		// 声明泛型集合,集合两端类型必须一致
		List<Object> list = new ArrayList<Object>();
		List<String> list1 = new ArrayList<String>();
		List list2 = new ArrayList<String>();
		List<Integer> list3 = new ArrayList();
		
		// 错误
		//List<Object> list4 = new ArrayList<String>();
		// 错误: 泛型类型必须是引用类型,不能为基本类型
		List<int> list5 = new ArrayList<int>();
	}

2.3 泛型的分类

2.3.1 泛型方法
	泛型方法:
			1.泛型的声明是在方法上。
			2.泛型是在调用泛型方法时创建的。

public class GenericDemo {

	// 定义泛型方法
	public <T> T save(T t) {
		return t;
	}
	
	public <T,K> T save(T t,K k) {
		return t;
	}
	
	// 测试方法
	@Test
	public void testMethod() throws Exception {
		// 使用泛型方法:  在使用泛型方法的时候,确定泛型类型
		save(1.0f, 1);
	}
}

2.3.2 泛型类
		泛型类:
			  1.泛型的声明是在类上
			  2.泛型的确立是在创建对象时。
public class GenericDemo<T> {

	// 定义泛型方法
	public <K> T save(T t,K k) {
		return null;
	}
	
	public void update(T t) {

	}
	
	// 测试方法
	@Test
	public void testMethod() throws Exception {
		
		// 泛型类:  在创建爱泛型类对象的时候,确定类型
		GenericDemo<String> demo = new GenericDemo<String>();
		demo.save("test", 1);
	}
}
2.3.3 泛型接口
		泛型接口:
			  1.泛型的声明是在接口上
/**
 * 泛型接口
 *
 * @param <T>
 */
public interface IBaseDao<T> {
	void save(T t );
	void update(T t );
}


2.3.4 泛型类、泛型接口的泛型确立
		+++ 泛型类、泛型接口
		
				1)继承泛型类、实现泛型接口时确立泛型
				2)继承泛型类、实现泛型接口时延长泛型的生命周期
						

继承泛型类、实现泛型接口时确立泛型

		继承泛型列,确立泛型
		public class PersonDao implements IBaseDao<Person>{}
			
		实现泛型接口,确立泛型
		public abstract class BaseDao implements IBaseDao<Person> {}
			

延长泛型时间

		继承泛型类,延长泛型的声明周期
		public class PersonDao<T> extends BaseDao<t>{}
		
		实现泛型接口,延长泛型的生命首期
		public abstract class BaseDao<T> implements IBaseDao<Person> {}

2.4 泛型关键字

泛型中: 
			?   		  指定只是接收值
			? extends  Number     泛型的上线,只能传入Number的子类
			? super    Number    泛型的下限,只能传入Number的父类

2.4.1 关键字 — ?
	public void save(List<?> list) {
		// 只能获取、迭代list;  不能编辑list
	}

	
	? 只能接受泛型集合,而不能编辑集合值。所以一般在方法参数中用。
	
			如果在方法中使用list.add(..)会报错。	


public class App_extends_super {
	
	//只带泛型特征的方法
	public void save(List<?> list) {
		// 只能获取、迭代list;  不能编辑list
	}

	@Test
	public void testGeneric() throws Exception {
		
		// ?  可以接收任何泛型集合, 但是不能编辑集合值; 所以一般在方法参数中用
		List<?> list = new ArrayList<String>();
		//list.add("");// 报错
	}
}
2.4.2 关键字 — extend 【上限】
	public void save(List<? extends Number> list) {
	}
	
	泛型的上限:传入的List集合,必须是Number的子类

public class App_extends_super {
	
	
	/**
	 * list集合只能处理 Double/Float/Integer等类型
	 * 限定元素范围:元素的类型要继承自Number类  (上限)
	 * @param list
	 */
	public void save(List<? extends Number> list) {
	}

	@Test
	public void testGeneric() throws Exception {
		List<Double> list_1 = new ArrayList<Double>();
		List<Float> list_2 = new ArrayList<Float>();
		List<Integer> list_3 = new ArrayList<Integer>();
		
		List<String> list_4 = new ArrayList<String>();
		
		// 调用
		save(list_1);
		save(list_2);
		save(list_3);
		//save(list_4);
	}
}

2.4.2 关键字 — super 【下限】
	public void save(List<? super String> list) {
	}

	
	传入的List集合,必须是String的父类

/**
 * 泛型, 涉及到一些关键字
 * 
 * Ctrl + shift + R   查看当前项目中类
 * Ctrl + shift + T   查看源码jar包中的类
 *
 */
public class App_super {
	
	
	/**
	 * super限定元素范围:必须是String父类   【下限】
	 * @param list
	 */
	public void save(List<? super String> list) {
	}

	@Test
	public void testGeneric() throws Exception {
		// 调用上面方法,必须传入String的父类
		List<Object> list1 = new ArrayList<Object>();
		List<String> list2 = new ArrayList<String>();
		
		List<Integer> list3 = new ArrayList<Integer>();
		//save(list3);
	}
}

2.5 泛型的反射(获取泛型参数化类型)

public class B  extends A<Admin>{
	
	@Test
	public void test1() {
		Class clazz=B.class;
		
		//返回直接父类对象(带有泛型参数化类型)
		Type type = clazz.getGenericSuperclass();
		
		ParameterizedType param=(ParameterizedType) type;
		
		//获取参数化类型
		Type[] types = param.getActualTypeArguments();
		
		Class t=(Class) types[0];
		
		System.out.println(t.getSimpleName()); //Admin
	}
}

发布了113 篇原创文章 · 获赞 0 · 访问量 1275

猜你喜欢

转载自blog.csdn.net/weixin_45602227/article/details/104548313