java之泛型

概述

泛型是JDK1.5以后才有的, 可以在编译时期进行类型检查,且可以避免频繁类型转化!

// 集合的声明 不使用泛型
List list = new ArrayList();
list.add("evan_qb");
list.add(1);
// 集合的使用 当不使用泛型时,会抛出运行时异常
String str = (String) list.get(1);
// 使用泛型
// 声明泛型集合的时候指定元素的类型  使用泛型后,当存储不同类型时,编译时期就会报错
List list = new ArrayList();
list.add("China");
//list.add(1);// 编译时期报错
String str = list.get(1); 

在运行时抛异常,和在编译时报错,显然,在编译时报错更容易定位错误

而且使用泛型也易于维护,不再鱼龙混杂,而是存储相同类型,易于维护,可以让你消除代码中的强制类型转换,同时获得一个附加的类型检查层,该检查层可以防止有人将错误类型的键或值保存在集合中。

泛型擦除

泛型只在编译时期有效,编译后的字节码文件中不存在有泛型信息!

泛型擦除实例

public void save(List p){
}
public void save(List d){  // 报错: 与上面方法编译后一样
}

泛型写法

正确写法:

List list = new ArrayList();
List list1 = new ArrayList();
List list2 = new ArrayList();
 
  

错误写法:

//泛型类型要一致
List list4 = new ArrayList();
// 泛型类型必须是引用类型,不能为基本类型
List list5 = new ArrayList();
 
  

泛型方法/泛型类/泛型接口

泛型方法:

// 定义泛型方法
public  T save(T t,K k) { 
	return null;
}
// 使用泛型方法:  在使用泛型方法的时候,确定泛型类型
save(1.0f, 1);

泛型类:

public class GenericDemo {
	// 定义泛型方法
	public  T save(T t,K k) {
		return null;
	}
}
// 泛型类:  在创建爱泛型类对象的时候,确定类型
GenericDemo demo = new GenericDemo();

泛型接口:

//定义泛型接口
public interface IBaseDao {
	void save(T t );
	void update(T t );
}

泛型接口类型确定:

实现泛型接口的类也是抽象,那么类型在具体的实现中确定或创建泛型类的时候确定

public class BaseDao implements IBaseDao {}

在业务实现类中直接确定接口的类型

public class PersonDao implements IBaseDao{}

泛型关键字:

在泛型中:

?               指定只是接收值

extends      元素的类型必须继承自指定的类

super         元素的类型必须是指定的类的父类

关键字  ?

//只带泛型特征的方法
public void save(List list) {
	// 只能获取、迭代list;  不能编辑list
}
// ?  可以接收任何泛型集合, 但是不能编辑集合值; 所以一般在方法参数中用
List list = new ArrayList();
//list.add("");// 报错

关键字:   extends【上限】

list集合只能处理 Double/Float/Integer等类型

限定元素范围:元素的类型要继承自Number类  (上限)

public void save(List list) {
}
List list_1 = new ArrayList();
List list_2 = new ArrayList();
List list_3 = new ArrayList();
		
List list_4 = new ArrayList();	
// 调用
save(list_1);
save(list_2);
save(list_3);
save(list_4); //报错

关键字 :  super【下限】

super限定元素范围:必须是父类(Object)或者本身(String)【下限】

public void save(List list) {
}
// 调用上面方法,必须传入String的父类
List list1 = new ArrayList();
List list2 = new ArrayList();
List list3 = new ArrayList();
save(list3);  //报错
 
  

泛型的反射

Type   接口,任何类型默认的接口!

包括: 引用类型、原始类型、参数化类型

List  list  =  new   ArrayList();

泛型集合:    list

集合元素定义:new   ArrayList();  中的String

参数化类型:  ParameterizedType

即:“ArrayList” 为参数化类型


泛型反射的案例:通用的jdbc方法

我们使用一个通用的BaseDao方法去存储基本的jdbc方法

由于本案例使用的数据库时Oracle数据库,还有DBUtil组件,所以需要导入相应的包

java之泛型_第1张图片

下面先写BaseDao类

public class BaseDao {
	private Class clazz;
	private String tableName;
	/**
	 *  构造函数: 
	 *  1. 获取当前运行类的参数化类型; 
	 *  2. 获取参数化类型中实际类型的定义(class)
	 */
	public BaseDao(){
		//  this  表示当前运行类  (AccountDao/StudentDao)
		//  this.getClass()  当前运行类的字节码(AccountDao.class/StudentDao.class)
		//  this.getClass().getGenericSuperclass();  当前运行类的父类,即为BaseDao
		//   ParameterizedType,其实就是“参数化类型”
		//获取当前运行类的父类,Type类型表示任意类型
		Type type = this.getClass().getGenericSuperclass();
		//强制转换为ParameterizedType(参数化)类型
		ParameterizedType pt = (ParameterizedType) type;
		// 获取参数化类型中类似【new Type[]{Account.class}】,获取实际的参数类型
		Type[] types = pt.getActualTypeArguments();
		//获取数据的第一个元素:Account.class
		clazz = (Class) types[0];
		//获取表名
		tableName = clazz.getSimpleName();
	}
	public T findById(int id){
		Connection conn = null;
		String sql = "select * from " + tableName + " where id = ?";
		try {
			conn = ConnectionFactory.getConnection();
			System.out.println(tableName);
			QueryRunner qr = new QueryRunner();
			return qr.query(conn,sql, new BeanHandler(clazz),id);
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}finally{
			ConnectionFactory.close(conn, null, null, null);
		}
	}
	/**
	 * 获取所有
	 * @return
	 */
	public List getAll(){
		Connection conn = null;
		String sql = "select * from " + tableName;
		try {
			conn = ConnectionFactory.getConnection();
			return new QueryRunner().query(conn, sql,new BeanListHandler(clazz));
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}finally{
			ConnectionFactory.close(conn, null, null, null);
		}
	}
}

当谁需要用到这些方法时,我们就将其继承BaseDao,然后我们可以通过反射泛型的技术,或者正在运行的类的类型,然后进行相应的CRUD操作,而每个子类只需要定义特有的jdbc的方法就行了

分别编写Account类和Student类继承BaseDao类

public class AccountDao extends BaseDao{
}
public class StudentDao extends BaseDao{
}

Student实体类

public class Student {
	private int id;
	private String stuName;
	private double money;
	//省略getter和setter方法构造方法toString()方法
}

Account实体类

public class Account {
	private int id;
	private String accountName;
	private double money;
//省略getter和setter方法构造方法toString()方法
}

对应的创建表的语句:

create sequence account_seq increment by 1 start with 1;
create sequence stu_seq increment by 1 start with 1;
create table account(
       id number(10),
       accountName varchar2(20),
       money number(10,2)
);
create table Student(
       id number(10),
       stuName varchar2(20),
       money number(10,2)
);

drop table student;

-- 插入数据到account表中
insert into account values(account_seq.nextval,'张三',1000.00);
insert into account values(account_seq.nextval,'李四',2000.00);

--插入数据到Student表中
insert into student values(stu_seq.nextval,'evan_qb',500.00);
insert into student values(stu_seq.nextval,'李四',1000.00);
commit

然后我们就来测试一波

StudentDao stuDao = new StudentDao();
List stus = stuDao.getAll();
for (Student stu : stus) {
System.out.println(stu);

运行结果如下:



AccountDao account = new AccountDao();
Account account1 = account.findById(1);
//List accounts = account.getAll();
System.out.println(account1);

运行结果如下:


这样,我们就用反射泛型实现了对jdbc的优化




你可能感兴趣的:(------,java反射技术,①java学习)