java中的反射(Reflection)
前言:
反射可以得到类或对象的所有属性与方法!比较官方一点的说法就是:JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
运用领域:
写框架需要运用到反射,有的业务也需要到反射(比如通过实体类生成sql,前提是表明必须按照特定的规则)。反射在重构代码中能起到很大的作用,也能减少相应的代码。缺点是反射多了会影响效率,但可以说是微乎其微了。
反射简单案例
1反射封装的方法,比较常见的有通过field设置 value与根据field取value的值。
/**
* @param fieldName 属性名
* @param obj 被取值对象
* @retrun 取到的值
* */
private Object getFieldValueByFieldName(String fieldName, Object obj) {
try {
Field field = obj.getClass().getDeclaredField(fieldName);
//设置对象的访问权限,保证对private的属性的访问
field.setAccessible(true);
return field.get(obj);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @param fieldName 属性名
* @param obj 需要设置属性值的对象
* @param value 内容
* */
private void setFieldValueByFieldName(String fieldName, Object obj,Object value) {
try {
Class c = obj.getClass();
Field f = c.getDeclaredField(fieldName);
f.setAccessible(true);
f.set(object,value);
} catch (Exception e) {
e.printStackTrace();
}
}
2.通过方法名运行带参方法
/**
* @param methodName 方法名
* @param obj 方法所在对象
* @param args 方法所需参数
* */
private static Object invokeMethod(String methodName, Object obj, Object... args) {
Object returnObj = null;
try {
Class<?>[] clazz = new Class[args.length];//定义一个类数组,因为方法参数可以是各种类型
for(int i=0;i<args.length;i++){
clazz[i] = args[i].getClass();//将参数匹配为相应的类型
}
Method method= obj.getClass().getMethod(methodName,clazz);//类型在这里使用
returnObj = method.invoke(obj, args);//参数在这里,Object万物皆对象
} catch (Exception e) {
e.printStackTrace();
}
return returnObj;
}
3.通过反射实体类生成sql语句,建表规则要遵循特定的规则才行。
/**
* 反射生成SQL语句的工具类
* 表名与字段的命名规则必须是下划线命名法
*/
public class ReflectSqlUtil {
private static BaseConditionalField conditionalField = new BaseConditionalField();
/**
* 生成插入语句
* @param tablename 表明
* @param clazz 与数据库中字段一一对应的类
* @param t 有数据的实体
* @param <T> 数据实体类型 如 User
*/
public static <T> String getInsertSql(String tablename, Class<T> clazz, T t){
//insert into table_name (column_name1,column_name2, ...) values (value1,value2, ...)
String sql = "";
Field[] fields = ReflectUtil.getFieldsDirectly(clazz, false);
StringBuffer topHalf = new StringBuffer("insert into "+tablename+" (");
StringBuffer afterAalf = new StringBuffer("values (");
for (Field field : fields) {
if ("ID".equals(field.getName()) || "id".equals(field.getName())){
continue; //id 自动生成无需手动插入
}
topHalf.append(humpToUnderline(field.getName()) + ",");
if (ReflectUtil.getFieldValue(t, field.getName()) instanceof String) {
afterAalf.append( ReflectUtil.getFieldValue(t, field.getName())==null?"'0',":"'" +ReflectUtil.getFieldValue(t, field.getName()) + "',");
} else {
afterAalf.append(ReflectUtil.getFieldValue(t, field.getName())==null?"0,":ReflectUtil.getFieldValue(t, field.getName()) + ",");
}
}
topHalf = new StringBuffer(StrUtil.removeSuffix(topHalf.toString(), ","));
afterAalf = new StringBuffer(StrUtil.removeSuffix(afterAalf.toString(), ","));
topHalf.append(") ");
afterAalf.append(") ");
sql = topHalf.toString() + afterAalf.toString();
return sql;
}
/**
* 生成更新语句
* 必须含有id
* 数据实体中 null 与 空字段不参与更新
* @param tablename 数据库中的表明
* @param clazz 与数据库中字段一一对应的类
* @param t 有数据的实体
* @param <T> 数据实体类型,如 User
*/
public static <T> String getUpdateSql(String tablename, Class<T> clazz, T t){
//UPDATE table_name SET column_name1 = value1, column_name2 = value2, ... where ID=xxx
//or
//UPDATE table_name SET column_name1 = value1, column_name2 = value2, ... where id=xxx
String sql = "";
// String id = ""; //保存id名:ID or id
Field[] fields = ReflectUtil.getFieldsDirectly(clazz, false);
sql = "update "+tablename+" set ";
for (Field field : fields) {
StringBuffer tmp = new StringBuffer();
if ("ID".equals(field.getName()) || "id".equals(field.getName())){
// id = field.getName();
continue;//更新的时候无需set id=xxx
}
if (ReflectUtil.getFieldValue(t, field.getName()) != null && ReflectUtil.getFieldValue(t, field.getName()) != "") {
tmp.append(humpToUnderline(field.getName()) + "=");
if (ReflectUtil.getFieldValue(t, field.getName()) instanceof String) {
tmp.append( "'" + ReflectUtil.getFieldValue(t, field.getName()) + "',");
} else {
tmp.append(ReflectUtil.getFieldValue(t, field.getName()) + ",");
}
sql += tmp;
}
}
//sql = StrUtil.removeSuffix(sql, ",") + " where " + id + "='" + ReflectUtil.getFieldValue(t, id)+"'";
//去除条件在xml中拼接
sql = StrUtil.removeSuffix(sql, ",");
return sql;
}
/***
* 驼峰命名转为下划线命名
* @param para 驼峰命名的字符串
*/
public static String humpToUnderline(String para){
StringBuilder sb=new StringBuilder(para);
int temp=0;//定位
if (!para.contains("_")) {
for(int i=0;i<para.length();i++){
if(Character.isUpperCase(para.charAt(i))){
sb.insert(i+temp, "_");
temp+=1;
}
}
}
return sb.toString().toUpperCase();
}
/**
* 获取条件语句sql
* @param tableBean 对象
* @param excludes 需要排除的条件
* @return
*/
public static String getConditionalSql(Object tableBean, List<String> excludes) {
StringBuffer conditionalSql = new StringBuffer();
JSONObject beanJson = JSONObject.parseObject(JSONObject.toJSONString(tableBean));
Class cls = conditionalField.getClass();
Field[] fields = cls.getDeclaredFields();
for(int i=0; i<fields.length; i++){
Field f = fields[i];
f.setAccessible(true);
if (beanJson.containsKey(f.getName())){
if (excludes != null && excludes.contains(f.getName())){
continue;
}
conditionalSql.append(" and ");
conditionalSql.append(humpToUnderline(f.getName()));
conditionalSql.append("=");
conditionalSql.append("'");
conditionalSql.append(beanJson.get(f.getName()));
conditionalSql.append("'");
}
}
return conditionalSql.toString();
}
/**
* 获取查询SQL
* @param tableName
* @return
*/
public static String getQuerySql(String tableName) {
StringBuffer querySql = new StringBuffer();
querySql.append("select * from ");
querySql.append(tableName);
querySql.append(" ");
return querySql.toString();
}
}
目前对反射的理解,后续会继续更新ing…