何为反射:Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
这句化很抽象!那我们该如何理解这句话呢?
我们都知道Java所有的类的默认继承Object类,Object类提供了一个public final native Class<?> getClass() 的方法,也就是说任何一个对象在程序运行期间都能知道他是那个类的实例。
不信我们写段代码来测试下:
运行结果:
运行结果说明我们确实可以在程序运行期间获取到该对象是那个类的实例。
那我们再来看看Class类又提供了哪些方法:
乍一看好多啊,那我们在平时的工作中到底该掌握哪些呢?
1、public T newInstance() 通过此方法可以调用类的默认构造器获取一个类的实例
2、public Constructor getConstructor(Class... parameterTypes) 通过此方法可以获取类的一个构造器
3、public Field[] getDeclaredFields() 通过此方法可以获取到类中的所用属性
4、public Method getMethod(String name, Class... parameterTypes) 根据方法名和参数类型来获取方法。(为啥还需要参数类型,因为Java用方法重载机制)
5、public Method[] getMethods() 获取类的所有方法
6、public native boolean isInstance(Object obj) 判断对象是不是类的实例
7、public native boolean isInterface() 判断类是不是接口类
8、public native boolean isArray(); 判断类是不是数组
还有很多方法我们就不一一介绍了,上面的这些方法只是我们在运用反射时比较常用的。如果你有兴趣了解可自行到官网查阅。
下面重点来了,我们如何使用这些方法呢。比如现在要让你做一个业务场景,对一个方法传过来的对象的所有属性值做非空校验。但是需要保证方法的通用性。那我们就可以这么写:
public static boolean checkProperty(Object object)throws Exception {
//获取所有属性
Field[] fields = object.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.get(object) !=null)return false;
}
return true;
}
这样我们在不必知道一个需要检验的类有哪些属性,只要他存在我们就能校验.我门也不需要管它的这个属性到底提供没提供访问方法。是不是很强大。
再比如说,我要写一个Excel的导入功能。正常程序员都是对于不同的表格写不同的方法来与之对应的解析,那么能不能所有的解析操作用一个方法就能解决呢。那么答案是肯定的。
public static <T> List<T> getExcelData(Class<T> clazz, Workbook workbook) throws Exception {
List list =new ArrayList<>();
Field[] fields = clazz.getClass().getDeclaredFields();
Sheet sheet = workbook.getSheet("要解析的表格");
for (int i =0; i < sheet.getLastRowNum(); i++) {
T object = clazz.newInstance();
for (int j =0; j < fields.length; j++) {
fields[j].set(object, sheet.getRow(i).getCell(j));
}
list.add(object);
}
return list;
}
上面的方法只是一个演示版本,很多细节都没有考虑。但是你能感觉到反射所带来的对一些规则性很强的业务可以做到很简洁的实现。我们不必对这些功能大致相同的东西都要费心费力的反复复制、粘贴,修改。大大提升了我们的工作效率。