反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。那我们该如何使用呢?
我们首先得运用java中的Class类,Class是一个类,一个描述类的类(也就是描述类本身),封装了描述方法的Method,描述字段的Filed,描述构造器的Constructor等属性。首先我们要使用这个类首先要去API查看该类的定义和使用方法,通过该类来获取自己所想要得到类的所有属性的一种通用写法:
Class>[] |
getDeclaredClasses() 返回 Class 对象的一个数组,这些对象反映声明为此 Class 对象所表示的类的成员的所有类和接口。 |
Constructor |
getDeclaredConstructor(Class>... parameterTypes) 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。 |
Constructor>[] |
getDeclaredConstructors() 返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。 |
Field |
getDeclaredField(String name) 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。 |
Field[] |
getDeclaredFields() 返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。 |
Method |
getDeclaredMethod(String name, Class>... parameterTypes) 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。 |
Metod[] |
getDeclaredMethods() 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。 |
//这都是运用反射机制常见的几个方法的相关介绍。下面给大家介绍一个完整的反射机制使用方法:
(1)首先创建一个BaseDao,在该类里面创建通用查询方法:
package com.Myweb.util;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
//创建BaseDAO类,里面声明了了连接类型Connection类,
PreparedStatement类,结果集类ResultSet类;
public class BaseDao {//创建了通用查讯类serachList类,返回结果类型是serachList,集合类型数据,因为可能查询到的数据不止一条,所以优先考虑List;
//该通用查询类有三个参数,第一个参数sql代表你要执行的sql语句,第二个参数pramps是你要传递你sql语句中所需要的参数值,因为考虑到参数可能不止一个,就用了数组Object[],因为不知道数组中参数的数据类型,这里会使用Object类,第三个参数clz代表的数据表所对应的封装类的类对象,代表这个类。
public static List> serachList(String sql,Object[] pramps,Class> clz){try {
//这里我用的是c3p0连接池进行获取连接对象的,最后会贴上C3p0Util类的代码
conn=C3p0Util.getConn();ps=conn.prepareStatement(sql);
//这句话首先判断查询的参数是否为空,不为空的话把对应的参数设置到preparedstatement类对象中,以便对sql语句进行处理。
if(pramps != null && pramps.length > 0){List
//调用PreparedStatement类的executeQuery()方法来进行查询操作,将查询的数据赋值给结果集对象rs。
以便对数据进行相应的操作。
rs=ps.executeQuery();
// rs.next()方法介绍,指针移动到当前位置的下一行。ResultSet 指针的初始位置位于第一行之前;第一次调用next()方法将会把第一行设置为当前行;第二次调用next()方法指针移动到第二行,以此类推。这样就可以把之前通过sql语句查询到的数据映射到对应的表结构,每次取一条数据来进行相应的操作,
while(rs.next()){
//当取到第一条数据,我们怎么取出对应的字段值,和所对应的列数,如何使用该查询到的数据呢?我们需要使用ResultSetMetaData接口,因为该接口可用于获取关于 ResultSet
对象中列的类型和属性信息的对象。以下代码片段创建 ResultSet
对象 rs,创建 ResultSetMetaData
对象metaData,并使用 metaData 查找 rs 有多少列,因为ResultSet类有方法来获取到ResultSetMetaData,以便对结果集对象进行操作
ResultSetMetaData metaData=rs.getMetaData();
下面给大家介绍几个ResultSetMetaData中的常用方法:
String |
getColumnClassName(int column) 如果调用方法 ResultSet.getObject 从列中获取值,则返回构造其实例的 Java 类的完全限定名称。 |
int |
getColumnCount() 返回此 ResultSet 对象中的列数。 |
int |
getColumnDisplaySize(int column) 指示指定列的最大标准宽度,以字符为单位。 |
String |
getColumnLabel(int column) 获取用于打印输出和显示的指定列的建议标题。 |
String |
getColumnName(int column) 获取指定列的名称。 |
int |
getColumnType(int column) 获取指定列的 SQL 类型 |
int count=metaData.getColumnCount();//获取结果集总列数;
创建javabean对象实例,代表的是数据表所对应的封装类,类中属性名最好和表中字段名一致;
Object obj=clz.newInstance();//获取类对象的实例;Field field=clz.getDeclaredField(colname);//通过列名获取到字段对象,就是我们所说的属性;
//当需要访问私有字段,属性,方法的时候需要调用setAccessible方法,取消Java访问权限检查机制,这样就可以访问私有属性了。
field.setAccessible(true);
//此处调用了Field类的set方法,就是给封装类对象所对应的字段赋值操作,这样数据表对应的封装类的对象类就有值了,相当于查询到了理想的结果。
field.set(obj, objvalue);//将指定对象变量上此 Field 对象表示的字段设置为指定的新值}
//因为考虑到查询的结果不止一条,用集合进行操作
myList.add(obj);//然后返回该结果集对象}finally{
//关闭连接池
C3p0Util.release(conn, ps, rs);}
//下面就是写了一个测试类来测试查询结果,
public class TestBaseDao {
public static void main(String[] args) {
// TODO Auto-generated method stub
//集合查询
String sql="select * from sf_user";
List
System.out.println(serachList);
}
查询结果如下图:
[User [id=1, username=dsc, password=123456, telphone=13995972425, sex=男, registDate=2018-04-20]
, User [id=2, username=xww, password=123456, telphone=13487251559, sex=女, registDate=2018-04-20]
, User [id=3, username=null, password=null, telphone=null, sex=null, registDate=null]
, User [id=4, username=dsc, password=123456, telphone=13995972425, sex=男, registDate=null]
, User [id=5, username=zxf, password=123456, telphone=13995972425, sex=女, registDate=null]
, User [id=6, username=rrr, password=123456, telphone=13995972425, sex=男, registDate=2018-04-20]
]