JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。
Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。
- package com.royzhou.reflect;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Field;
- import java.lang.reflect.Method;
- public class ReflectTest {
- private String id;
- private String name;
- public String property;
- public String getId() {
- return id;
- }
- public void setId(String id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getProperty() {
- return property;
- }
- public void setProperty(String property) {
- this.property = property;
- }
- public ReflectTest() {
- System.out.println("this is a constructor with no params!!!");
- }
- public ReflectTest(String param) {
- System.out.println("this is a constructor with param :" + param
- + "!!!");
- }
- /**
- * 创建对象
- *
- * @param clazz
- * @param paramTypes:构造函数参数,如果为null表示调用无参函数
- * @return
- * @throws Exception
- */
- public Object createObject(Class clazz, Class[] paramTypes)
- throws Exception {
- Object obj = null;
- if (paramTypes == null) {
- // 无参构造函数
- obj = clazz.newInstance();
- } else {
- // 有参构造函数
- Constructor con = clazz.getConstructor(paramTypes);
- obj = con.newInstance("Test String param");
- }
- return obj;
- }
- /**
- * 激活对象的某个方法
- *
- * @param obj
- * @param methodName
- * @throws Exception
- */
- public void invokeMethod(Object obj, String methodName) throws Exception {
- Method[] methods = obj.getClass().getDeclaredMethods(); // 拿到当前类的全部方法,包括私有的和公有的
- methods = obj.getClass().getMethods(); // 拿到当前类以及父类的所有公有方法
- for (Method m : methods) {
- if (m.getName().equals(methodName)) {
- m.invoke(obj, new Object[] {}); // 调用方法
- }
- }
- }
- public void getFileds(Object obj) throws Exception {
- Field[] fields = obj.getClass().getFields(); // 获取公有的属性
- fields = obj.getClass().getDeclaredFields(); // 获取公有私有属性
- for (Field f : fields) {
- System.out.println(f.getName());
- }
- }
- public void overload(String s) {
- System.out.println("param is String :" + s);
- }
- public void overload(int i) {
- System.out.println("param is int :" + i);
- }
- public void testInvoke() {
- System.out.println("this is a method for invoke test!!!");
- }
- public static void main(String[] args) throws Exception {
- ReflectTest rt = new ReflectTest();
- Object obj = rt.createObject(ReflectTest.class, null);
- System.out.println("--------------");
- obj = rt.createObject(ReflectTest.class, new Class[] { String.class });
- System.out.println("--------------");
- rt.invokeMethod(obj, "testInvoke");
- System.out.println("--------------");
- Method m = obj.getClass().getMethod("overload", int.class);
- m.invoke(obj, new Object[] { 1 });
- System.out.println("--------------");
- m = obj.getClass().getMethod("overload", String.class);
- m.invoke(obj, new Object[] { "test overload String" });
- System.out.println("--------------");
- rt.getFileds(obj);
- }
- }
利用java的反射机制可以进行简单的ORM即对象关系映射
如下面代码:
- import java.lang.reflect.Method;
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.ResultSetMetaData;
- import java.util.ArrayList;
- import java.util.List;
- public class ORMTest {
- /**
- * @param args
- * @throws Exception
- */
- public static void main(String[] args) throws Exception {
- User user = (User) getObject(
- "select id as Id, name as Name from user where id=1",
- User.class);
- System.out.println(user);
- }
- public static List<Object> getObjects(String sql, Class clazz)
- throws Exception {
- Connection conn = null;
- PreparedStatement ps = null;
- ResultSet rs = null;
- try {
- conn = JdbcUtils.getConnection();
- ps = conn.prepareStatement(sql);
- rs = ps.executeQuery();
- String[] colNames = getColNames(rs);
- List<Object> objects = new ArrayList<Object>();
- Method[] ms = clazz.getMethods();
- while (rs.next()) {
- Object object = clazz.newInstance(); //
- for (int i = 0; i < colNames.length; i++) {
- String colName = colNames[i];
- String methodName = "set" + colName;
- for (Method m : ms) {
- if (methodName.equals(m.getName())) {
- m.invoke(object, rs.getObject(colName));
- break;
- }
- }
- objects.add(object);
- }
- }
- return objects;
- } finally {
- JdbcUtils.free(rs, ps, conn);
- }
- }
- private static String[] getColNames(ResultSet rs) throws Exception {
- ResultSetMetaData rsmd = rs.getMetaData();
- int count = rsmd.getColumnCount();
- String[] colNames = new String[count];
- for (int i = 1; i <= count; i++) {
- colNames[i - 1] = rsmd.getColumnLabel(i);
- }
- return colNames;
- }
- public static Object getObject(String sql, Class clazz) throws Exception {
- Connection conn = null;
- PreparedStatement ps = null;
- ResultSet rs = null;
- try {
- conn = JdbcUtils.getConnection();
- ps = conn.prepareStatement(sql);
- rs = ps.executeQuery();
- String[] colNames = getColNames(rs);
- Object object = null;
- Method[] ms = clazz.getMethods();
- if (rs.next()) {
- object = clazz.newInstance();
- for (int i = 0; i < colNames.length; i++) {
- String colName = colNames[i];
- String methodName = "set" + colName;
- for (Method m : ms) {
- if (methodName.equals(m.getName())) {
- m.invoke(object, rs.getObject(colName));
- break;
- }
- }
- }
- }
- return object;
- } finally {
- JdbcUtils.free(rs, ps, conn);
- }
- }
- }
在这个简单的ORM中,利用Java的反射机制动态创建实例,不需要事先知道要生成什么对象或对象集合,只需要在调用的时候转型(当然也可以使用jdk1.5的泛型技术),使用m.invoke(object, rs.getObject(colName))方法动态设置实例的属性,注意,在这个例子中,user类必须是一个标准的Javabean,具有各个属性的setter/getter方法以及一个没有参数的构造函数,上面例子中使用sql的别名来实现动态调用对象的方法,(Hibernate使用配置文件.hbm.xml文件完成数据库字段到javabean的映射),只需要在写查询sql的时候指定好别名就可以完成javabean属性的设置。
假如有另外一个类 Product
- public class Product {
- private String id;
- private String name;
- private String manufatrue;
- public String getId() {
- return id;
- }
- public void setId(String id) {
- this.id = id;
- }
- public String getManufatrue() {
- return manufatrue;
- }
- public void setManufatrue(String manufatrue) {
- this.manufatrue = manufatrue;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Product() {
- }
- }
这样我们在查询的时候只需要执行下面语句就可以获得封装好的Product对象/集合
- Product product= (Product ) getObject("select id as Id, name as Name ,manufature as Manufature from product where id=1",Product .class);
这样的代码更具有动态性,不用每个查询写一个查询方法