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

Posted hehy0205

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了反射技术菜鸟从入门到精通相关的知识,希望对你有一定的参考价值。

 

技术图片

前言

俗话说得好:“反射反射,程序员的快乐” 。用好反射,可以使你的开发效率事半功倍。反射技术作为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瞬间搞定。

 

 

不说了,我去喝可乐了!

 

 

 

技术图片

 

以上是关于反射技术菜鸟从入门到精通的主要内容,如果未能解决你的问题,请参考以下文章

反射从入门到精通

反射从入门到精通

HTML5从入门到精通的内容介绍

反射的理解

求:HTML5+CSS3从入门到精通.pdf

DDD(领域驱动设计)从入门到精通