java反射

来源:互联网 发布:scala java bean 编辑:程序博客网 时间:2024/06/06 01:12

弄Spring时又遇到了它,之前留下的影响已经比较模糊,就比较系统在去弄一遍

class对象保存类型信息,反射的动态运行加载等的理论信息虽然看过一遍java编程思想,但仍有很多的不理解的地方

现在的情况结合和之前定下的基调,所以一切以实用为基本,理论理解为辅,先学会去用,再慢慢的理解理论

所有代码完成成功运行

主要的内容

      1、获取class对象及类型信息

      2、反射的基本实用,Method、Field和Constructor

      3、简单使用反射对数据库新增保留功能的封装


1、获取class对象及类型信息,获取class对象的三种方法,获取类型信息有很多的get方法,例如getInterfaces()    getSuperclass()获取接口和父类信息  

//1、对象的getClass() 2、Class的静态方法forName() 3、.class方法Class<?> c = object.getClass();//Class<?> c1 = Class.forName("");//Class<?> c2 = User.class;


2、反射的基本实用,Method、Field和Constructor

//一、获取并操作方法Method[] methods = c.getMethods();Method method_1 = c.getMethod("testPrint", String.class);//方法名和参数类型method_1.invoke(object, "TestTest");//调用这个方法,类的对象和传递的参数//二、获取并操作属性Field[] fields = c.getFields();for(Field f : fields ){System.out.println(f);}//get--获取的是访问权限是public,包括父类的  ; getDeclared--获取的是所有访问权限的,不包括父类Field[] fields_2 = c.getDeclaredFields();for(Field f : fields_2){System.out.println(f);}AccessibleObject.setAccessible(fields_2, true);//设置private的课访问属性为truefor(Field f : fields_2){if(f.getName() == "name"){f.set(object, "ooooo");}else if(f.getName() == "phone"){f.set(object, "999999");}else{continue;}}Method m2 = c.getMethod("setField");m2.invoke(object);for(Field f : fields_2){System.out.println(f.get(object));//具体属性值}Field f1 = c.getDeclaredField("name");//根据属性名字单个获取f1.setAccessible(true);f1.set(object, "oooo");Field f2 = c.getDeclaredField("phone");f2.setAccessible(true);f2.set(object, "123456");Field[] fields_3 = new Field[2];fields_3[0] = f1;fields_3[1] = f2;System.out.println(f1.get(object));//三、创建类的实例Object object_1 = c.newInstance();//创建无参构造函数实例System.out.println(object_1.toString());//创建有参构造函数实例Object object_2 = c.getDeclaredConstructor(int.class,String.class,String.class).newInstance(1,"yyyy","8888");System.out.println(object_2.toString());String className = c.getName();String tableName = className.substring(className.lastIndexOf(".")+1, className.length());//看看几个的区别System.out.println(object); //对象所属包,所属类,对象引用地址System.out.println(c);//class对象。对象所属包,所属类System.out.println(className);//class包名和类名System.out.println(tableName);//取出其中的类名for(Method method : methods){System.out.println(method);}


  3、简单使用反射对数据库新增保留功能的封装

public void save(Object object) throws Exception{//1、根据传过来的对象组装 插入的sql语句//2、使用jdbc执行sql语句完成数据库操作String sql = "INSERT INTO";Class<?> c = object.getClass();String className = c.getName();//根据类名获得相应的表明String tableName = className.substring(className.lastIndexOf(".")+1, className.length());//如果要确实封装dao,实现save保存新增的方法,肯定不能出现具体的字段名,都是必须通过反射获得的//如果在框架中组装sql然后执行,只是封装底层,直接使用ORM方式更加方便,使用相应的get和set方法/*sql += " "+ tableName + " (id,name,password)  VALUES  (";Method method_5 = c.getMethod("getId");int id = (int) method_5.invoke(object);Method method_3 = c.getMethod("getName");String name = (String) method_3.invoke(object);Method method_4 = c.getMethod("getPassword");String password = (String) method_4.invoke(object);sql += id + ",'" + name + "','" + password +"')";*///拼接sql有蛮多的问题,保持必要的空格和字符的引号。进过一次坑就回对这些有感觉了//第一种有点类似于ssh框架下对sql的拼接//第二种封装save,即直接传入参数调用save方法,拼接sql的工作交出去,实际的封装更好的表达,更兼容的数据格式,这里只是体现思想sql += " "+ tableName + "  (";Method[] methods = c.getMethods();//保存数据库中相应的字段名List<String> nameList = new ArrayList<String>();//保存相应的字段值        List<Object> valueList = new ArrayList<Object>();        for (Method method : methods) {            String methodName = method.getName();            if (methodName.startsWith("get") && !methodName.startsWith("getClass")) {                String fieldName = methodName.substring(3, methodName.length());                nameList.add(fieldName);                try {                    Object value = method.invoke(object);                    if (value instanceof String) {                        valueList.add("'" + value + "'");                    } else {                        valueList.add(value);                    }                } catch (Exception e) {                    e.printStackTrace();                }            }        }        //拼接sql        for (int i = 0; i < nameList.size(); i++) {            if (i < nameList.size() - 1) {                sql += nameList.get(i) + ",";            } else {                sql += nameList.get(i) + ") values (";            }        }        for (int i = 0; i < valueList.size(); i++) {            if (i < valueList.size() - 1) {                sql += valueList.get(i) + ",";            } else {                sql += valueList.get(i) + ")";            }        }try {conn = JDBCUtil.getConnection();stmt = conn.prepareStatement(sql);stmt.execute();} catch (Exception e) {e.printStackTrace();}finally {JDBCUtil.closeAll(rs, stmt, conn);}

完整的代码

User类

package TestJDBC;import java.sql.Date;public class User {private int id;private String name;private String password;private String phone;private Date birthday;public User(int id, String name, String password, String phone, Date birthday){this.id = id;this.name = name;this.password = password;this.phone = phone;this.birthday = birthday;}public User(){}public User(int id, String name, String password){this.id = id;this.name = name;this.password = password;}public User(int id, String name, String password, String phone){this.id = id;this.name = name;this.password = password;this.phone = phone;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}@Overridepublic String toString(){ return id +" "+ name + " "+ phone + " " + password +" "+ birthday;}//为测试反射新建的方法public void testPrint(String info){System.out.println(info);}public void setField(){System.out.println(name + "的电话是" +phone);}}

JDBC工具类JDBCUtil类

package TestJDBC;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;//JDBC工具类,  加载驱动   建立连接    关闭资源 。方法都是static,可以直接调用public final class JDBCUtil {private static String DRIVER = "com.mysql.jdbc.Driver";private static String URL = "jdbc:mysql://localhost:3306/test";private static String USER_NAME = "admin";private static String PASSWORD = "123456";    //注册驱动放在静态代码块中,保证只注册一次,当类装载到虚拟机中就会执行static{try {Class.forName(DRIVER);} catch (Exception e) {e.printStackTrace();}}//建立连接public static Connection getConnection() throws SQLException{return DriverManager.getConnection(URL, USER_NAME, PASSWORD);}//释放资源public static void closeAll(ResultSet rs, Statement stmt, Connection conn){try {if(rs != null){rs.close();}rs = null;} catch (Exception e) {e.printStackTrace();}finally {try {if(stmt != null){stmt.close();}stmt = null;} catch (Exception e) {e.printStackTrace();}finally {try {if(conn != null){conn.close();}conn = null;} catch (Exception e) {e.printStackTrace();}}}}}

dao接口(习惯面向接口编程)

package ReflectTest;public interface IDao {public void save(Object object) throws Exception;}
dao的实现类

package ReflectTest;import java.lang.reflect.Method;import java.lang.reflect.AccessibleObject;import java.lang.reflect.Field;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.util.ArrayList;import java.util.List;import TestJDBC.JDBCUtil;import TestJDBC.User;public class DaoForReflect implements IDao {private static Connection conn = null;private static PreparedStatement stmt = null;private static ResultSet rs = null;public void reflectTest(Object object) throws Exception{//1、对象的getClass() 2、Class的静态方法forName() 3、.class方法Class<?> c = object.getClass();//Class<?> c1 = Class.forName("");//Class<?> c2 = User.class;//一、获取并操作方法Method[] methods = c.getMethods();Method method_1 = c.getMethod("testPrint", String.class);//方法名和参数类型method_1.invoke(object, "TestTest");//调用这个方法,类的对象和传递的参数//二、获取并操作属性Field[] fields = c.getFields();for(Field f : fields ){System.out.println(f);}//get--获取的是访问权限是public,包括父类的  ; getDeclared--获取的是所有访问权限的,不包括父类Field[] fields_2 = c.getDeclaredFields();for(Field f : fields_2){System.out.println(f);}AccessibleObject.setAccessible(fields_2, true);//设置private的课访问属性为truefor(Field f : fields_2){if(f.getName() == "name"){f.set(object, "ooooo");}else if(f.getName() == "phone"){f.set(object, "999999");}else{continue;}}Method m2 = c.getMethod("setField");m2.invoke(object);for(Field f : fields_2){System.out.println(f.get(object));//具体属性值}Field f1 = c.getDeclaredField("name");//根据属性名字单个获取f1.setAccessible(true);f1.set(object, "oooo");Field f2 = c.getDeclaredField("phone");f2.setAccessible(true);f2.set(object, "123456");Field[] fields_3 = new Field[2];fields_3[0] = f1;fields_3[1] = f2;System.out.println(f1.get(object));//三、创建类的实例Object object_1 = c.newInstance();//创建无参构造函数实例System.out.println(object_1.toString());//创建有参构造函数实例Object object_2 = c.getDeclaredConstructor(int.class,String.class,String.class).newInstance(1,"yyyy","8888");System.out.println(object_2.toString());String className = c.getName();String tableName = className.substring(className.lastIndexOf(".")+1, className.length());//看看几个的区别System.out.println(object); //对象所属包,所属类,对象引用地址System.out.println(c);//class对象。对象所属包,所属类System.out.println(className);//class包名和类名System.out.println(tableName);//取出其中的类名for(Method method : methods){System.out.println(method);}}public void save(Object object) throws Exception{//1、根据传过来的对象组装 插入的sql语句//2、使用jdbc执行sql语句完成数据库操作String sql = "INSERT INTO";Class<?> c = object.getClass();String className = c.getName();//根据类名获得相应的表明String tableName = className.substring(className.lastIndexOf(".")+1, className.length());//如果要确实封装dao,实现save保存新增的方法,肯定不能出现具体的字段名,都是必须通过反射获得的//如果在框架中组装sql然后执行,只是封装底层,直接使用ORM方式更加方便,使用相应的get和set方法/*sql += " "+ tableName + " (id,name,password)  VALUES  (";Method method_5 = c.getMethod("getId");int id = (int) method_5.invoke(object);Method method_3 = c.getMethod("getName");String name = (String) method_3.invoke(object);Method method_4 = c.getMethod("getPassword");String password = (String) method_4.invoke(object);sql += id + ",'" + name + "','" + password +"')";*///拼接sql有蛮多的问题,保持必要的空格和字符的引号。进过一次坑就回对这些有感觉了//第一种有点类似于ssh框架下对sql的拼接//第二种封装save,即直接传入参数调用save方法,拼接sql的工作交出去,实际的封装更好的表达,更兼容的数据格式,这里只是体现思想sql += " "+ tableName + "  (";Method[] methods = c.getMethods();//保存数据库中相应的字段名List<String> nameList = new ArrayList<String>();//保存相应的字段值        List<Object> valueList = new ArrayList<Object>();        for (Method method : methods) {            String methodName = method.getName();            if (methodName.startsWith("get") && !methodName.startsWith("getClass")) {                String fieldName = methodName.substring(3, methodName.length());                nameList.add(fieldName);                try {                    Object value = method.invoke(object);                    if (value instanceof String) {                        valueList.add("'" + value + "'");                    } else {                        valueList.add(value);                    }                } catch (Exception e) {                    e.printStackTrace();                }            }        }        //拼接sql        for (int i = 0; i < nameList.size(); i++) {            if (i < nameList.size() - 1) {                sql += nameList.get(i) + ",";            } else {                sql += nameList.get(i) + ") values (";            }        }        for (int i = 0; i < valueList.size(); i++) {            if (i < valueList.size() - 1) {                sql += valueList.get(i) + ",";            } else {                sql += valueList.get(i) + ")";            }        }try {conn = JDBCUtil.getConnection();stmt = conn.prepareStatement(sql);stmt.execute();} catch (Exception e) {e.printStackTrace();}finally {JDBCUtil.closeAll(rs, stmt, conn);}}}

main类

package ReflectTest;import TestJDBC.User;//动态public class Reflect {public static void main(String[] args) throws Exception {User user = new User(17,"yl","yll");DaoForReflect dao = new DaoForReflect();dao.save(user);}}



----------------------------------------------------------------OVER--------------------------------------------------------------------------


0 0