JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
首先我们看个反射的小例子。
1.我们新建一个User的类。
2.通过反射获取User对象的属性和方法。
package com.lb.op;
public class User {
private int id;
private String name;
public User() {
super();
}
public User(int id, String name) {
super();
this.id = id;
this.name = name;
}
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;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + "]";
}
}
(注意:该实例中要有系统默认的无参构造方法,否则后面通过反射实例对象时会报错)
/**
* 通过反射获取对象的属性和方法
* @param object
*/
public static void ReflectDemo(Object object){
System.out.println("对象名:");
System.out.println(object.getClass().getSimpleName());
//获取包括公共的、受保护的、默认的(包)访问和私有属性,但是不包括继承的属性。
Field[] fd = object.getClass().getDeclaredFields();
System.out.println("所有属性:");
for(Field field:fd) {
//将属性设置为可见的,主要是获取包括private在内的所有属性
field.setAccessible(true);
//属性修饰
String fieldModifier = Modifier.toString(field.getModifiers());
//属性类型
String fieldType = field.getType().getSimpleName();
//属性名
String fieldName = field.getName();
System.out.println(fieldModifier+" "+fieldType+" "+fieldName);
}
//获取包括公共的、受保护的、默认的(包)访问和私有方法,但是不包括继承的方法。
Method[] md = object.getClass().getDeclaredMethods();
System.out.println("所有方法:");
for(Method method:md) {
//将方法设置为可见的,主要是获取包括private在内的所有方法
method.setAccessible(true);
//方法修饰
String methodModifier = Modifier.toString(method.getModifiers());
//方法类型
String methodType = method.getReturnType().getSimpleName();
//方法名
String methodName = method.getName();
System.out.println(methodModifier+" "+methodType+" "+methodName);
}
}
运行的结果如下:
对象名:
User
所有属性:
private int id
private String name
所有方法:
public String toString
public String getName
public int getId
public void setName
public void setId
通过这个例子我们可以将反射比作一面镜子,它能照射出对象的所有内容。
那我们可以运用反射做些什么事情呢?就拿用最原始的例子来说,当我们用jdbc操作数据库时,你会发现我会要写好多好多增删改查的函数,有几个对象我们可能就要写几个,当对象一多时我们就能发现里面的共同点。
当我们查询所有信息时,你会发现查询不同的对象的信息时不同的就是那句sql语句和保存结果集的泛型,因此我们可以通过面向抽象编程实现这类查询的公共方法。
第一步:我们拼出sql语句
/**
* 创建查询所有信息的sql语句 即:select * from tablename;
* @param object
* @return
*/
public static String CreateSelectAllSql(Object object) {
StringBuffer sb = new StringBuffer();
sb.append("select * from ");
//类名一般是大写字母开头,数据库表权威小写
sb.append(object.getClass().getSimpleName().toLowerCase()+";");
System.out.println("生成的sql:"+sb);
return sb.toString();
}
第二步:查询数据,获取类的属性,最后保存结果集。
/**
* 通用查询方法
* @param servlet
* @param object
* @return
*/
public static ArrayList<Object> SelectAll(HttpServlet servlet,Object object){
ArrayList<Object> list = new ArrayList<Object>();
//这里是通过web.xml里的参数获得连接对象,你可以改成其他方式
Connection con = DateBaseTools.con_db(servlet);
ResultSet rs = null;
Statement st;
//生成的sql语句
String sql = CreateSelectAllSql(object);
System.out.println("传入的sql:"+sql);
try {
st=(Statement) con.createStatement();
rs=st.executeQuery(sql);
while(rs.next()){
System.out.println("one record");
//实例化一个对象
Object record = object.getClass().newInstance();
//获取对象的所有属性
Field[] fields = object.getClass().getDeclaredFields();
//判断属性的类型
for(Field field : fields){
//将所有属性设置成可见的
field.setAccessible(true);
//通过属性的类型调用不同的获取方法
switch(field.getType().getSimpleName()){
case "String":
field.set(record, rs.getString(field.getName()));
break;
case "int":
field.set(record, rs.getInt(field.getName()));
break;
}
}
list.add(record);
}
}catch(Exception e) {
e.printStackTrace();
}
System.out.println(list.size());
return list;
}
这样既可以做到通用查询!