java反射

弄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的课访问属性为true
		for(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;
	}
	@Override
	public 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的课访问属性为true
		for(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--------------------------------------------------------------------------


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值