反射获取类中成员变量
package com.woniu.demo03;
import com.woniu.demo01.Person;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class TestField {
public static void main(String[] args) {
//获取Person类的类类型实例
Class<Person> clazz = Person.class;
//Field[] fields = clazz.getFields(); //获取所有的public的字段,父类中也能获取到
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// System.out.println(field.getModifiers());
// System.out.println(field.getType().getTypeName());
System.out.print(field.getType().getSimpleName()+" ");
System.out.println(field.getName());
}
System.out.println("-------------------------------------------------------------");
try {
//获取单个字段
// Field field = clazz.getField("name");
Field field = clazz.getDeclaredField("name");
//为某个对象的该字段赋值
Object obj = clazz.newInstance();
//field.setAccessible(true); //暴力反射
//比较正统的写法,将字段的访问转给对应getter和 setter
//field.set(obj,"小明");
String setName = "set"+field.getName().substring(0,1).toUpperCase()+field.getName().substring(1);
//set方法的参数类型就是访问的字段的类型
Method setMethod = clazz.getMethod(setName,field.getType());
setMethod.invoke(obj,"小明");
field.setAccessible(true); //暴力反射
//访问field的值
Object val = field.get(obj);
System.out.println("访问字段的值:"+val);
} catch (Exception e) {
e.printStackTrace();
}
}
}
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class TestList {
public static void main(String[] args) {
List<Integer> lst = new ArrayList<>();
List lst2 = new ArrayList();
System.out.println(lst.getClass() == lst2.getClass()); //输出为true
lst.add(111);
lst.add(222);
//lst.add("hello");
try {
//通过反射绕过编译,直接获取lst对象对应的Class信息
Class c = lst.getClass();
Method method = c.getMethod("add", Object.class);
method.invoke(lst,"hello");
System.out.println(lst);
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.反射应用 - 封装JDBC的Dao方法
类似于Apache DbUtils.jar工具类库
1. 创建db.properties文件 ,通过JdbcUtil类加载jdbc驱动相关的信息
2. 定制UserDao类,实现JDBC操作add(User user),List<User> getList();基本功能
3. 在JdbcUtil类中定制静态方法 int executeUpdate(String sql,Object...params)方法,封装insert,update,delete操作
4. 在JdbcUtil类中定制静态方法 定制 List<T> executeQuery(String sql,Class<T> clazz,Object...params)封装查询列表[反射应用]
5. 以User表(id,username,password)为例,测试上述方法
step1: db.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
jdbc.user=root
jdbc.pass=root
step2: JdbcUtil.java
package com.woniu.util;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**
* JdbcUtil工具类
*/
public class JdbcUtil {
private static String url;
private static String driverClass;
private static String username;
private static String password;
/**
* 静态块
*/
static {
try {
//读取properties文件
Properties props = new Properties();
InputStream inStream = JdbcUtil.class.getClassLoader().getResourceAsStream("db.properties");
props.load(inStream);
inStream.close();
//获取jdbc 的四大属性信息
url = props.getProperty("jdbc.url");
driverClass = props.getProperty("jdbc.driver");
username = props.getProperty("jdbc.user");
password = props.getProperty("jdbc.pass");
} catch (Exception exception) {
exception.printStackTrace();
System.out.println("添加properties配置文件失败");
}
}
/**
* 获取 Connection连接对象
*
* @return
*/
public static Connection getConnection() {
try {
//加载驱动类字节码信息到JVM中的方法区
Class.forName(driverClass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
System.out.println("未找到驱动类....");
}
try {
Connection conn = DriverManager.getConnection(url, username, password);
return conn;
} catch (SQLException throwables) {
throwables.printStackTrace(); //便于调试程序
System.out.println("建立连接失败");
}
return null;
}
/**
* 释放资源
*
* @param conn
* @param pstmt
* @param rs
*/
public static void closeAll(Connection conn, PreparedStatement pstmt, ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
try {
if (pstmt != null) {
pstmt.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
//测试Connection
public static void main(String[] args) {
Connection conn = JdbcUtil.getConnection();
System.out.println(conn != null ? "连接成功" : "连接失败");
}
}
封装insert,update,delete
step3: 定制UserDao类
public class UserDao {
/**
* 添加操作
*/
public boolean add(User user){
String sql ="insert into user_info(username,password) values(?,?)";
Connection conn = JdbcUtil.getConnection();
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(sql);
//为sql语句传参
pstmt.setString(1,user.getUsrename());
pstmt.setString(2,user.getPassword());
//执行Sql
int rows = pstmt.executeUpdate();
if(rows>0){
return true;
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
JdbcUtil.closeAll(conn,pstmt,null);
}
return false;
}
}
step4: 定制JdbcUtil类中的工具方法
public static int executeUpdate(String sql,Object...params){}
/**用于封装Dao类中的insert,delete,update操作*/
public static int executeUpdate(String sql,Object...params) {
Connection conn = JdbcUtil.getConnection();
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(sql);
//为sql语句传参
for(int i=0;i<params.length;i++){
pstmt.setObject(i+1,params[i]);
}
//执行Sql
int rows = pstmt.executeUpdate();
return rows;
} catch (SQLException e) {
e.printStackTrace();
}finally{
JdbcUtil.closeAll(conn,pstmt,null);
}
return 0;
}
step5:测试工具类中的executeUpdate(String sql ,Object...params)
public class DaoTest {
public static void main(String[] args) {
UserDao userDao = new UserDao();
User user = new User();
user.setUsername("李四");
user.setPassword("111");
boolean flag = userDao.add(user);
System.out.println(flag ? "添加成功" : "添加失败");
}
}
封装select查询
/**封装Dao类中的select查询方法操作*/
public static <T> List<T> executeQuery(Class<T> clazz,String sql,Object...params){
//创建空的List集合对象用于封装结果并返回
List<T> list = new ArrayList<>();
Connection conn = JdbcUtil.getConnection();
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
pstmt = conn.prepareStatement(sql); //初始化预编译SQL语句
//为sql设置参数
setParams(pstmt, params);
//执行查询
rs = pstmt.executeQuery();
while(rs.next()){ //读取一行
try {
//创建需要封装查询结果的单个实体对象
T obj = clazz.newInstance();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
String fieldName = field.getName(); //获取当前迭代的字段的名称
// //暴力反射
// field.setAccessible(true);
// //如果实体类中字段的名称与查询结果集中的列名一致
// field.set(obj,rs.getObject(fieldName));
//不使用暴力反射的正统写法
String methodName = "set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
Method method = clazz.getMethod(methodName,field.getType());
method.invoke(obj,rs.getObject(fieldName));
}
//添加集合List
list.add(obj);
} catch (Exception e) {
e.printStackTrace();
}
}
return list;
} catch (SQLException e) {
e.printStackTrace();
} finally{
JdbcUtil.closeAll(conn,pstmt,rs);
}
return null;
}
//传统方式的赋值
public void setProperty(Object obj, String propertyName, Object value) {
//获取字节码数据
Class<?> clazz = obj.getClass();
try {
//获取类字段
Field declaredField = clazz.getDeclaredField(propertyName);
//通过字段获得set方法名称
String setProperty = "set" + declaredField.getName().substring(0, 1).toUpperCase(Locale.ROOT) + declaredField.getName().substring(1);
//通过类对象,方法名,方法参数获取对应方法对象
Method method = clazz.getMethod(setProperty, declaredField.getType());
//执行方法
method.invoke(obj, value);
} catch (Exception e) {
e.printStackTrace();
}
}
//单表查询
public static <T> List<T> getList(Class<T> clazz, String sql, Object... params) {
List<T> list = new ArrayList<>();
Connection conn = JdbcUtil.getConnection();
PreparedStatement pst = null;
ResultSet rs = null;
try {
pst = conn.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
pst.setObject(i + 1, params[i]);
}
rs = pst.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
while (rs.next()) {
try {
T t = clazz.newInstance();
Field[] fields = clazz.getDeclaredFields();
JdbcUtil jdbcUtil = new JdbcUtil();
for (Field field : fields) {
//暴力破解方法
// field.setAccessible(true);
// field.set(t, rs.getObject(field.getName()));
//传统方法
//判断数据库总列数
for (int i = 1; i <= rsmd.getColumnCount(); i++) {
//通过列数获取列名 与 字段名做比较 一致则进行赋值 不一致则赋值为null
if (field.getName().toString().equals(rsmd.getColumnLabel(i))) {
jdbcUtil.setProperty(t, field.getName(), rs.getObject(field.getName()));
}
// else {
// jdbcUtil.setProperty(t, field.getName(), null);
// }
}
}
list.add(t);
} catch (Exception e) {
e.printStackTrace();
}
}
return list;
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtil.closeAll(conn, pst, rs);
}
return null;
}
// 多表连接查询 方法的封装
// List<Map<String,Object>> executeQueryForMulti(String sql,Object...params)
public static List<Map<String, Object>> executeQueryForMulti(String sql, Object... params) {
List<Map<String, Object>> list = new ArrayList<>();
Connection conn = JdbcUtil.getConnection();
PreparedStatement pst = null;
ResultSet rs = null;
try {
pst = conn.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
pst.setObject(i + 1, params[i]);
}
rs = pst.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
while (rs.next()) {
Map<String,Object> map = new HashMap<>();
try {
for (int i = 1; i <= rsmd.getColumnCount(); i++) {
map.put(rsmd.getColumnName(i),rs.getObject(i));
}
list.add(map);
} catch (Exception e) {
e.printStackTrace();
}
}
return list;
} catch (SQLException e) {
e.printStackTrace();
} finally {
JdbcUtil.closeAll(conn, pst, rs);
}
return null;
}