今天主要是 队列 循环队列的学习。以及反射的应用,基于反射我们学习了如何只做一个通用的dao层。利用这个基本逻辑处理类我们可以实现对于数据库的插入和查看。当然剩下的方法还没有写,一会儿尝试写出来。不过最好先把刚刚那段代码抄一遍,然后背一下。做到融会贯通。然后其实可以再背一遍JDBCTemplate模板。
队列与循环队列:
这个 版本的反射的应用应该是 1.0版本的。比起前面那一张的那个 坑爹类,可强太多了。只有3个方法,但是 要展示的 反射的应用 却用的比较到位。
以下例程
队列:
package MyQueue; public class MyQueue {//线性队列 private Object[] obs = new Object[5]; private int start=-1;//队头 private int end=-1;//队尾 /** * 添加元素,这个可以封装Object[] 当然也可把我们昨天写的链表结构拿过来,用作对象的存储 * @param object */ public void add(Object object){ if(end>=obs.length){ System.out.println("队列已满"); return ; } obs[++end]=object; } /** * 得到队列的开始元素 * @return */ public Object getStart(){ return obs[start+1]; } /** * 得到队尾元素 * @return */ public Object getEnd(){ return obs[end]; } /** * 得到队列的长度 * @return */ public int getSize(){ return end-start; } /** * 出队操作 * @return */ public Object putOut(){ start++; Object object = obs[start]; obs[start]=null; return object; } /** * 按照队列顺序查看队列中的元素 */ public void lookout(){ for(int i=start+1;i<end+1;i++){ System.out.println(obs[i]); } } }
循环队列:
package MyQueue; /** * 线性队列的存在总是很爽,但是很浪费空间,如果每次都能让队列满载,这样就很节省空间。 * @author Administrator *浪费一个空间作为队满的标志 *修改的时候,总是要记得%,不能直接++ *对比的时候也要记得,% */ public class MyCircleQueue { Object[] obs = new Object[5]; private int start=0;//队头 private int end=0;//队尾 /** * 为循环队列添加元素 * @param object */ public void add(Object object){ if(isFull()){ System.out.println("队列已满,请等待"); return ; } end=(end+1)%obs.length; obs[end]=object; } /** * 判断队列是否已满,消耗一个空间用作队满的标志 * @return */ public boolean isFull(){ return (end+1)%obs.length==start; } /** * 判断队列是否为空,如果start==(end)%obs.length 则队空 * @return */ public boolean isEmpty(){ return (end)%obs.length==start; } /** * 出队操作,里面的队头不可能大于5,所以 上面关于 队满和队空的判断是合理的。并不用为strat也进行求余操作。 * @return */ public Object putout(){ if(isEmpty()){ System.out.println("队列中没有元素"); return null; } Object object = obs[start]; obs[start]=null; start=(start+1)%obs.length; return object; } /** * 得到循环队列中等待元素的数量 * @return */ public int getSize(){//如果数组短还好,可以直接访问得到数据个数,如果数组长了这样就不划算了,应该可以有算法 //数组长度一定小于obs.length() int i=0; for(;i<obs.length;i++){ if((end+i)%obs.length==start){ break; } } return obs.length-i; } /** * 按照队列顺序额查看队列中的元素 */ public void lookout(){ if(isEmpty()){ System.out.println("队列为空"); return ; } int i=0; while((start+i)%obs.length!=(end+1)%obs.length){ System.out.println(obs[(start+i)%obs.length]); i++; } } }
基于jdbc的template:
package com.letben.dao; import java.lang.reflect.GenericArrayType; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import com.letben.bean.user_tb; import com.letben.util.JDBCTemplate; /** * 当前BaseDao使用的前提是:类名和表名要保持一致,属性名和字段名要保持一致 * 之后我们会写一个映射表,来解决数据库和表名命名需要符合规范的问题 * @author Administrator * 抽空补齐 改 和删! */ public class BaseDao extends JDBCTemplate{ /* static String className=null; static String tableName = null; * 并且发现老师的代码里面每一个地方都有className。所以不妨在程序开始的时候,写一个出来。 * 表名也是 BaseDao(){} BaseDao(Class c){ className = c.getName(); tableName = className.substring(className.lastIndexOf(".")+1); } static { //静态块儿并实现不了,需要一个构造函数 } * 类型安全问题,是不是可以把List后面加一个泛型。 * @param c * @return * 不不不,这些东西不能放在BaseDao,里面而要放在对应的 user_tb 的dao里面 */ public void addObject(Object obj){ Class c = obj.getClass(); String className = c.getName(); String tableName = className.substring(className.lastIndexOf(".")+1); StringBuffer sql = new StringBuffer(); // 对于我们要反复修改的字符串语句来讲,我们最好使用StringBuffer 以节省空间。每new的一个String都会在内存中占用一个地址 //组拼sql语句: insert into tableName (column1,column2...) values (value1,value2...); sql.append(" insert into "); sql.append(tableName); List<String> fields = new ArrayList<String>(); List values = new ArrayList(); Method[] methods = c.getMethods(); for (Method method : methods) { //组拼时,需要对应的属性和值,那么新建了两个集合,通过整体添加的方式保持两者对应一致。 String methodName = method.getName(); if(methodName.startsWith("get")&&!methodName.equalsIgnoreCase("getclass")){ String fieldName = methodName.substring(3); fields.add(fieldName); try { values.add(method.invoke(obj, new Object[]{})); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } } sql.append(" ( ");//这个里面空格可以多不能少,所以尽量在每一个单词前后都加上空格,以免字符连在一起,sql无法解析 for(int i=0;i<fields.size();i++){ if(i==fields.size()-1){ sql.append(fields.get(i)); }else{ sql.append(fields.get(i)+","); } } sql.append(" ) "); sql.append(" values "); sql.append(" ( "); for (int i = 0; i < values.size(); i++) { if(i==values.size()-1){ sql.append("'"+values.get(i)+"'"); }else{ sql.append("'"+values.get(i)+"',"); } } sql.append(" ) "); System.out.println(sql.toString()); updateData(sql.toString()); } public Object getObjectById(Class c,int id){ String className = c.getName();//大类名 String tableName = className.substring(className.lastIndexOf(".")+1);//表名,因为我们的前提是类名与表名一致 String sql = "select * from "+tableName+" where id = "+id; ResultSet resultSet = query(sql); Object object = null; try { object = c.newInstance(); if(resultSet.next()){ Method[] methods = c.getMethods(); for (Method method : methods) { String methodName = method.getName(); if(methodName.startsWith("set")){ String fieldName = methodName.substring(3); Class[] cla=method.getParameterTypes(); if(cla[0]==String.class){//要求属性和字段都放是String和name的依然没有那么通用 method.invoke(object, new Object[]{resultSet.getString(fieldName)}); }else{ method.invoke(object, new Object[]{resultSet.getInt(fieldName)}); } //method.invoke(object,new Object[]{resultSet.getString(fieldName)}); //取不出来,事实证明真的不通用,只能是对应的读取 } } } } catch (SQLException e) {//resultSet.next(); e.printStackTrace(); } catch (InstantiationException e) {//c.newInstance e.printStackTrace(); } catch (IllegalAccessException e) {//c.newInstance e.printStackTrace(); } catch (IllegalArgumentException e) {//invoke e.printStackTrace(); } catch (InvocationTargetException e) {//invoke e.printStackTrace(); } return object; } public List getAllObject(Class c){ String className = c.getName();//得到类名 System.out.println(className); String tableName = className.substring(className.lastIndexOf(".")+1);//得到表名或者 类的类名。 System.out.println(tableName); String sql = "select * from "+ tableName; ResultSet resultSet = query(sql);//这是JDBCTemplate里面的方法 // System.out.println("****************"); List list = new ArrayList(); Object object = null; try{ while(resultSet.next()){ object=c.newInstance(); Method[] methods = c.getMethods();//得到所有公开的方法。 for (int i=0;i<methods.length;i++){ Method m=methods[i];//得到当前遍历到的这个方法 // System.out.println(m); String methodName = m.getName(); // System.out.println(methodName); if(methodName.startsWith("set")){//如果这个方法以set开头 String fieldName = methodName.substring(3);//得到对应属性名称 Class[] cla = m.getParameterTypes();//得到m方法的全部参数的参数类型。 if(cla[0]==String.class){ // m.invoke(object, new Object(){}); //方法召唤,反射得到的方法再进行调用,先传一个类作为实际使用这个方法的参数进去,后面是参数列表 m.invoke(object,resultSet.getString(fieldName)); //等效于:object.set<fieldName>(resultSet.getString(fieldName)); //即:对象把从结果集里面取出来的属性值赋给对应的属性。 }else{ m.invoke(object, resultSet.getInt(fieldName)); //我们常见的getters和setters的语句是:对象.setField(FieldValue); //在反射里面这样写: 方法(对象,参数们)所以针对参数们:的标准写法是:new Object(){p1,p2...} } } } //这些轮完一圈儿,说明一个对象已经赋值完成。可以使用。故: list.add(object); object=null; } }catch(Exception e){ e.printStackTrace(); } return list; } public static void main(String[] args) { BaseDao baseDao= new BaseDao(); List<com.letben.bean.user_tb> list =baseDao.getAllObject(user_tb.class);//刚刚到这里有点儿蒙,忘记了类名.class for (user_tb user_tb : list) { System.out.println(user_tb); } } }
那个 jdbc:刚写过了【笑哭】去那篇名叫jdbc的blog里面找一下吧