- 概念
- 在运行状态中,对于任意一个类,都能够知道类的所有属性和方法;对于任意一个对象,都能够调用他的任意一个方法。这就是java的反射机制
- 用法
- 获取Class实例
- 使用Class实例可以获取泛型所指对象的方法、属性、注解等,还可以调用方法操作该类,具体哪些方法可以在java.lang.Class类中查看
- 实际应用
- 需求:从mdb文件中解析N多张表入库,可以通过反射拼写sql语句一次性执行。
- 实现:
获取Class实例的几种方式 //通过全限定类名获取 Class<Father> aClass = Class.forName(classname); //通过Object中的getClass方法 //object that represents the runtime class of this object这是Object中对于getClass方法的说明:为object获取运行时的class Class<Father> aClass = new Father().getClass() //类.class Class<Father> aClass = Father.class //一定要注意aClass到底是谁的实例,在继承或者传参的时候容易出错 1.父类的引用指向子类的对象 Father f = new Children(); Class<Children> aClass = f.getClass; Class<Father> aClass = Father.class 注意以上分别代表谁的Class实例 2.当使用对象传参的时候,例如方法是使用Object接收的 //假设有一个get方法需要传一个对象 //我使用Father对象传参调用get方法 get(new Father()); public void get(Object object){ //当Father对象传递过来以后我们需要得到Class实例进行操作 //此时的Class对象是Object的 Class<?> aClass = object.getClass(); //得到Father的全限定类名 String classname = aClass.getName(); //此时的Class对象才是Father的 Class<?> myClass = Class.forName(classname); }
//此处Object作为一个参数传递,因为我们并不知道传过来的是要入库的哪个实体 public static void saveData(String ywh,Object obj) throws Exception { //解析mdb Connection conn = null; Statement stmt = null; String filePath = "C:\\Users\\xd\\Desktop\\成果包\\140000山西省空间规划数据库电子成果数据\\4表格数据\\140000山西省国土空间规划指标表.mdb"; String conStr = "jdbc:ucanaccess:///" + filePath; DbUtils.loadDriver("net.ucanaccess.jdbc.UcanaccessDriver"); conn = DriverManager.getConnection(conStr); stmt = conn.createStatement(); //获取全限定类名 String classname = obj.getClass().getName(); //得到真正想要入库的对象 而不是Object的Class实例 Class<?> aClass = Class.forName(classname); String[] split = classname.split("\\."); classname = split[split.length-1]; String sql = "select * from "+classname; QueryRunner queryRunner = new QueryRunner(); //注意aClass是真正要入库的对象,如果上面不做Class.forName处理,那么得到是Object,而达不到我们想要的结果 List<Object> list = (List<Object>) queryRunner.query(conn,sql,new BeanListHandler(aClass)); list.forEach(item -> { try { //获取对应的属性,这里使用的是暴力反射获取属性,因为属性在对象中定义的是private Field f = item.getClass().getDeclaredField("ywh"); Field primary = item.getClass().getDeclaredField("ID"); try { //private属性的操作需要设置setAccessible为true primary.setAccessible(true); f.setAccessible(true); //赋值:将字符串ywh赋值给list中的对象的ywh属性,f即反射得到的ywh的属性对象 f.set(item,ywh); //赋值:将字符串UUID赋值给list中的对象的ID属性,primary即反射得到的ID的属性对象 primary.set(item, IdGen.uuid()); } catch (IllegalAccessException e) { e.printStackTrace(); } } catch (NoSuchFieldException e) { e.printStackTrace(); } }); if(list.size()>0){ save(list,classname); } } public static void save(List<Object> list,String classname) { //获取目标对应的所有属性列表 Field[] fields = list.get(0).getClass().getDeclaredFields(); //将所有属性装到list中,并且拼接成字符串供后面使用 List<String> nameList = new ArrayList<>(); String insertstr = ""; for(int i=0;i<fields.length;i++){ nameList.add(fields[i].getName()); insertstr+=fields[i].getName()+","; } insertstr = insertstr.substring(0,insertstr.length()-1); //类名 即 表名 String tablename = "insert into xxhacheck."+classname.toLowerCase()+"("+insertstr+") values (" ; String allsql = ""; //循环拼接sql语句 for(Object obj: list){ String valuestr = ""; //为了获取list中每个对象的所有属性值 for(int i=0;i<fields.length;i++){ String fieldname = fields[i].getName(); try { //反射获取属性对象Field,属性私有使用getDeclaredField Field declaredField = obj.getClass().getDeclaredField(fieldname); declaredField.setAccessible(true); //利用属性对象获取属性值 Object value = declaredField.get(obj); if(value==null){ valuestr+="无 "+","; }else{ valuestr+=value.toString()+","; } } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } } valuestr = valuestr.substring(0,valuestr.length()-1); System.out.println("拼接以后的值:"+valuestr); String finalstr = tablename+valuestr+");"; allsql+=finalstr; } System.out.println("最终的结果值:"+allsql); }
记录一次项目Java反射的应用
最新推荐文章于 2024-07-13 15:29:04 发布