反射技术菜鸟从入门到精通(一)

前言

俗话说得好:“反射反射,程序员的快乐” 。用好反射,可以使你的开发效率事半功倍。反射技术作为Java特性,已经成为框架构建的基础。如果灵活掌握反射,可谓“一步登天”!

什么是反射?

JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

Java的反射机制是在编译并不确定是哪个类被加载了,而是在程序运行的时候才加载、操作。使用在编译期并不知道的类,这样的特点就是反射。

反射的作用?

  1. 由于众多框架都是用到了反射机制(例如Spring的IOC与AOP,Hibernate的对象实体关系映射),学了反射我们可以更好的学习框架;
  2. 根据反射的特点,我们可以通过反射来了解类的构成,做出一系列比较通用的工具代码(也就是框架);
  3. 将许多代码变为自动化实现,以此达到减少开发周期的目的。
  4. 节约下来的时间可以和美女愉快的交流,或者躲在角落处快乐的喝肥宅水^_^(这条比较关键!)

Case1:

  我们在做JDBC查询数据库时,希望把数据库中的多条记录保存到java中的一个List中对象,例如将Scott的EMP(oracle示例表,oracle安装后自带)表的数据放到java中的Emp的对象中,然后再将Emp的对象放到一个集合中:

package cn.gzsxt.test;
  
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import cn.gzsxt.model.Emp;
import cn.gzsxt.util.DBUtil;

public class TestEmp {
public List getAllEmp() { List list = new ArrayList<>(); Connection conn = DBUtil.getConnection(); PreparedStatement ps = null; ResultSet rs = null; try { String sql = "select * from emp"; ps = conn.prepareStatement(sql); rs = ps.executeQuery(); while (rs.next()) { // 创建一个Emp的对象 Emp e = new Emp(); e.setEmpno(rs.getInt("empno")); e.setEname(rs.getString("ename")); e.setJob(rs.getString("job")); e.setMgr(rs.getInt("mgr")); e.setHiredate(rs.getDate("hiredate")); e.setSal(rs.getDouble("sal")); e.setComm(rs.getDouble("comm")); e.setDeptno(rs.getInt("deptno")); list.add(e); } } catch (SQLException e) { e.printStackTrace(); } finally { DBUtil.close(conn, ps, rs); } return list; } }

 

写过JDBC的同学都清楚,红色部分代码的意义是创建对象,并为对象的属性赋值。这些操作其实是“没有意义的体力活”。如果下次查询Dept表,还要创建Dept对象,所以我们可以利用反射将其封装成一个方法:

package cn.gzsxt.test;

import java.lang.reflect.Field;
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; import cn.gzsxt.util.DBUtil;

public class TestEmp { // 目的:将数据库中的一行记录转化为java中一个对象 public List rows2beans(String sql, Class cls) { List list = new ArrayList(); Connection conn = DBUtil.getConnection(); PreparedStatement ps = null; ResultSet rs = null; try { ps = conn.prepareStatement(sql); rs = ps.executeQuery(); // 每一个rs对象都对应一个ResultSetMetaData对象 ResultSetMetaData rsmd = rs.getMetaData(); // 获取查询的列数 int count = rsmd.getColumnCount(); while (rs.next()) { Object object = cls.newInstance(); //cls决定生成什么对象 for (int i = 0; i < count; i++) { // 获取第一列的名字 String fieldName = rsmd.getColumnName(i + 1).toLowerCase(); // 通过列名获取类中的属性的表述对象 Field field = cls.getDeclaredField(fieldName); // 根据set方法名获取set方法对应的表述对象 Method m = cls.getDeclaredMethod(getSetMethodName(fieldName), field.getType()); Object objval = rs.getObject(fieldName); if (objval != null) { if (objval instanceof Number) { if (field.getType().getName().equals("int")) { m.invoke(object, rs.getInt(fieldName)); } else if (field.getType().getName().equals("long")) { m.invoke(object, rs.getLong(fieldName)); } else if (field.getType().getName().equals("double")) { m.invoke(object, rs.getDouble(fieldName)); } else if (field.getType().getName().equals("short")) { m.invoke(object, rs.getShort(fieldName)); } else if (field.getType().getName().equals("byte")) { m.invoke(object, rs.getByte(fieldName)); } else if (field.getType().getName().equals("float")) { m.invoke(object, rs.getFloat(fieldName)); } } else { m.invoke(object, objval); } } } list.add(object); } } catch (Exception e) { e.printStackTrace(); } finally { DBUtil.close(conn, ps, rs); } return list; }
   // 根据属性名获取该属性的set方法的名字
public String getSetMethodName(String fieldName) { return "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); }

 

至此,我们就完成了对任意一条SQL语句的查询封装,尽管这个方法还有很多不如意的地方,比如:sql没有参数。但不管怎么说这个方法使用起来就很方便了,我们只需要给定sql语句以及要生成的类型即可得到一个有关一张表数据的List,一起来看main方法:

public static void main(String[] args) {
    
    List list = obj.rows2beans("select * from emp", Emp.class);
    System.out.println(list.size()) //数据为14条

}

好啦,今天的分享就到这里了!这个封装的方法大家可以保存起来,以后懒得写查询数据库的代码时,ctrl+c和ctrl+v瞬间搞定。

不说了,我去喝可乐了!下次老王继续和你分享Java World!

 

  

转载于:https://www.cnblogs.com/laownag/p/10770890.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值