java之泛型

来源:互联网 发布:网络红人马浩东前女友 编辑:程序博客网 时间:2024/05/17 03:23

概述

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

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

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

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

泛型擦除

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

泛型擦除实例

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

泛型写法

正确写法:

List<Object> list = new ArrayList<Object>();List<String> list1 = new ArrayList<String>();List list2 = new ArrayList<String>();

错误写法:

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

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

泛型方法:

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

泛型类:

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

泛型接口:

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

泛型接口类型确定:

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

public class BaseDao<T> implements IBaseDao<T> {}

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

public class PersonDao implements IBaseDao<Person>{}

泛型关键字:

在泛型中:

?               指定只是接收值

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

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

关键字  ?

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

关键字:   extends【上限】

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

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

public void save(List<? extends Number> list) {}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); //报错

关键字 :  super【下限】

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

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

泛型的反射

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

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

List<String>  list  =  new   ArrayList<String>();

泛型集合:    list

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

参数化类型:  ParameterizedType

即:“ArrayList<String>” 为参数化类型


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

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

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


下面先写BaseDao类

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

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<Student> stus = stuDao.getAll();for (Student stu : stus) {System.out.println(stu);

运行结果如下:



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

运行结果如下:


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




原创粉丝点击