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;
//一、获取并操作方法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
- 【反射】JAVA反射机制
- JAVA 反射
- java 反射
- Java反射
- java反射
- java反射
- JAVA反射
- java 反射
- Java 反射
- java 反射
- Java反射
- java反射
- JAVA 反射
- java 反射
- Java反射
- java反射
- java 反射
- java 反射
- python数组的使用
- hbase建表语句
- expect匹配不上,执行一段时间自动输出匹配的内容问题
- 《RESTful Web Services》学习笔记
- 博客开通
- java反射
- DrawerLayout侧滑布局点击不响应事件
- 线程取消(pthread_cancel)
- android studio 一键生成bean 插件GsonFormat的使用
- JAVA之杨辉三角实现
- Mina学习笔记(一) 简单服务端实例
- 适配器模式,装饰模式,代理模式异同
- leetcode 3. Longest Substring Without Repeating Characters
- js两条直线(可自动延伸)的交点坐标