Java反射:解析类的秘密
Java反射是一项强大的功能,允许开发人员在运行时检查、操作和实例化类、方法、字段以及其他Java程序中的元素。这种能力赋予了Java语言更大的灵活性和动态性,但也需要慎重使用,因为它可能会导致性能问题和安全漏洞。
反射的核心思想是使开发人员能够检查类的结构、字段和方法,而无需在编译时明确知道这些信息。它提供了一种机制,通过这种机制,您可以在运行时获取类的信息,包括其名称、字段、方法和构造函数。这使得您可以在不直接依赖于编译时类型信息的情况下创建通用代码和工具。
Java反射的主要用途包括:
- 动态实例化对象: 您可以在运行时创建类的实例,而不需要在编译时知道类的名称。
- 访问类的信息: 您可以获取类的名称、字段、方法和注解等信息,以便进行高级元编程。
- 调用方法和操作字段: 您可以动态调用类的方法和操作类的字段值,使得编写通用的代码变得更容易。
尽管Java反射提供了很多强大的功能,但也需要小心使用。它可能会导致性能下降,因为在运行时获取信息通常比在编译时知道信息更昂贵。此外,反射操作可能会绕过编译时的类型检查,因此如果不小心使用,可能会导致运行时异常。另外,反射也会对代码的安全性产生潜在的威胁,因此需要谨慎处理。
实际使用举例
这里介绍一下个人会用反射的时候:
有的时候,我们需要将一个VO对象转换为map集合,如果VO字段字段很多很多,那么这个过程就会比较麻烦。
如easy-poi 工具类导出excel时就需要这样操作。
网上肯定有对应的工具类可以用,不过我遇到这个问题时还是自己写了一个,原理也很简单,直接反射获取对象字段名放到map的key里,值放value里
方法如下:
/**
* 将类的字段名存入map集合中
*/
public static <T> void getClassFieldNameTOMap(Class objectClass, Map<String,String> map,T o) throws NoSuchFieldException, IllegalAccessException {
Field[] fields = objectClass.getDeclaredFields();
Field nameField;
for (Field field : fields) {
nameField = objectClass.getDeclaredField(field.getName());
//抑制java语言访问检查 ,操作私有属性
nameField.setAccessible(true);
map.put(field.getName(),null == nameField.get(o) ? "": nameField.get(o).toString());
}
}
使用示例:
@Data
public class ExcelVO {
private String columnCode;
private String columnName;
private String cnName;
}
public static void main(String[] args) {
ExcelVO excelVO = new ExcelVO();
excelVO.setCnName("中文名");
excelVO.setColumnCode("列名");
excelVO.setColumnName("列说明");
Map<String, String> map = new HashMap<>();
try {
ReflectUtils.getClassFieldNameTOMap(ExcelVO.class, map, excelVO);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
map.forEach((k, v) -> System.out.println(k + ":" + v));
}
后记:
最初,写反射方法是考虑为了检查sql server数据库插入字段过长的,之前项目里用pgSQL,字段过长时报错会直接提示哪个字段过长,但是有的项目用sqlserver没这功能,插入字段过长只会报错什么将截断字符串或二进制数据,表几百个字段检查起来真的麻。