1310 字
7 分钟
Java反射机制
Java反射机制
反射的概念
在运行时加载、探知、使用编译期间完全未知的classes
加载类
Class类
所有加载的类也是一个对象,这些对象共有的行为特征抽象为Class类,加载的类就是一个一个的Class对象
如何获得Class对象
- Class.forName(“包名.类型”) :
//获得Person类的类对象 try { Class cls = Class.forName("com.hyxy.Person"); } catch (ClassNotFoundException e) { e.printStackTrace(); }使用场景: 编译环境中没有Person类时
- 类名.class : 编译的字节码文件中,默认有一个静态的class属性,存储了这个类的对象
//获得Person类的类对象 Class cls = Person.class;使用场景:编译环境中有Person类,最直接的方式
- 对象.getClass方法
//获得Person类的类对象 Person p = new Person(); Class cls = p.getClass();使用场景:编译环境中有类,现在持有一个对象,但是不知道这个对象的类型,要获得这个对象的类对象
public static void method(Object obj){ //获得参数obj的类对象 Class cls = obj.getClass(); }Class类的方法
- getName方法 : 包名+类名
- getSimpleName方法: 获取类名
- newInstance方法:创建类对象对应类的对象,这个方法实质还是调用了类无参构造器,已过时(后续要获得构造器对象来创建对象)
- getDeclaredField(String name) :通过名字获得属性对象
- getDeclaredFields : 获得所有属性,得到的是属性数组(Field[])
- getDeclaredMethod(String methodName,Class … parameterType) : 通过方法名和参数类型列表获得一个方法对象
- getDeclaredConstructor(Class … parameterType) : 通过参数类型列表获得一个构造器
Field类
每个Field对象就是类中的某个属性的实例,Field对象中包含属性名、属性类型、属性值的属性
对属性的操作包括 : 对象属性的赋值和取值操作
方法:
- 设置属性可访问: setAccessable
- 设置对象的属性值: set(Object obj,Object value)
- 获取对象的属性值: get(Object obj)
实例:获取学生类的姓名、年龄、序号三个属性对象,对某个学生对象的三个属性复制、获取某个学生对象的三个属性值
package com.hyxy; import java.lang.reflect.Field; public class Test { public static void main(String[] args) { try { //Student的类对象 Class stuCls = Class.forName("com.hyxy.Student"); //创建一个Student对象 Object obj = stuCls.newInstance(); //通过属性名获取三个属性对象 Field fleld1 = stuCls.getDeclaredField("name"); Field fleld2 = stuCls.getDeclaredField("age"); Field fleld3 = stuCls.getDeclaredField("no"); //设置这个属性是可访问 fleld1.setAccessible(true); //为obj对象(Student对象)的name属性赋值为tom fleld1.set(obj,"tom"); System.out.println(fleld1.get(obj)); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } }}Method类
每个对象代表了类中一个一个方法实例,对方法的操作主要是执行方法
方法:
invoke方法: 执行方法,需要传入实参
public class Test { public static void main(String[] args) { try { //Student的类对象 Class stuCls = Class.forName("com.hyxy.Student"); //创建一个Student对象 Object obj = stuCls.newInstance(); //获得student对象的study()方法 Method method1 = stuCls.getDeclaredMethod("study"); //获得student对象的study(String lession,int time)方法 Method method2 = stuCls.getDeclaredMethod("study",String.class,int.class); //获得student对象的study(int time,String lession)方法 Method method3 = stuCls.getDeclaredMethod("study",int.class,String.class); //执行method1方法 method1.invoke(obj); //执行method2方法,传入的字符串是"abc",传入的时间是24 method2.invoke(obj,"abc",24); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }Constructor构造器
方法:
newInstance方法: 调用构造器创建对象,需要传入实参
实例:
public class Test { public static void main(String[] args) { try { //Student的类对象 Class stuCls = Class.forName("com.hyxy.Student"); //获得构造器 Constructor constructor = stuCls.getDeclaredConstructor(String.class,int.class,int.class); Object obj = constructor.newInstance("tom",20,110011); Student student = (Student)obj; System.out.println(student.getName()+","+student.getAge()+","+student.getNo()); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }反射实现通用DAO的二层封装
DAO的二层封装:每个表都要写一个对应的DAO,原因是每个表的SQL语句是不同的,那么通过反射技术,将VO对象的类名作为表名、属性名作为列表,就可以动态的拼出每个表的SQL语句了,通过反射就可以用一个DAO实现SQL语句的封装,在通用DAO中要完成的事情:
- 获得VO参数的类对象
- 获得VO参数对象的类名和所有属性名
- 拼写SQL语句
- 使用JDBC执行SQL语句
实现DAO:
package com.hyxy.dao; import com.hyxy.vo.T_User; import org.apache.commons.dbutils.QueryRunner;import java.lang.reflect.Field;import java.sql.Connection;import java.sql.SQLException;import java.util.ArrayList;import java.util.List;import java.util.Map;public class CommonDao { public int insert(Object obj,String pkName,boolean isAutoIncre){ Class cls = obj.getClass(); //类名作为表名 String tableName = cls.getSimpleName(); String columnJoinStr = ""; String wenhaoJoinStr = ""; Field[] flelds = cls.getDeclaredFields(); List<String> columnNameList = new ArrayList<>(); List<String> wenhaoList = new ArrayList<>(); List<Object> valueList = new ArrayList<>(); String[] names = new String[columnNameList.size()]; for(Field fleld:flelds){ fleld.setAccessible(true); columnNameList.add(fleld.getName()); if(fleld.getName().equals(pkName)&&isAutoIncre){ wenhaoList.add("default"); }else{ wenhaoList.add("?"); try { valueList.add(fleld.get(obj)); } catch (IllegalAccessException e) { e.printStackTrace(); } } } columnJoinStr = String.join(",",columnNameList.toArray(names)); wenhaoJoinStr = String.join(",",wenhaoList.toArray(new String[wenhaoList.size()])); String sql = "insert into "+tableName+"("+columnJoinStr+") " + "values("+wenhaoJoinStr+")"; System.out.println(sql); Connection conn = DBUtil.getConnection(); QueryRunner queryRunner = new QueryRunner(); int result = 0; try { result = queryRunner.execute(conn,sql,valueList.toArray()); } catch (SQLException e) { e.printStackTrace(); } return result; } public int update(Object obj,String pkName){ return 0; } public int delete(Class cls,String pkName,Object pkValue){ return 0; } public Object queryById(Class cls,String pkName,Object pkValue){ return null; } public List<Object> query(Class cls, Map<String,Object> map){ return null; } public static void main(String[] args) { CommonDao commonDao = new CommonDao(); T_User user = new T_User(); user.setUsername("test123"); user.setPwd("123456"); user.setEmail("4324342@qq.com"); commonDao.insert(user,"id",true); }}MySQL基础
Related articles
部分信息可能已经过时