当前位置: 首页 > 科技观察

担心被问-反省,给你勇气

时间:2023-03-16 12:16:54 科技观察

\本文转载自微信公众号《狼王编程》,作者狼王。转载本文请联系狼王编程公众号。这篇文章,我们就来说说什么是反射,以及为什么很多程序员一听到反射就莫名害怕。这篇文章给了你勇气,其实并没有多少!在Java中,想要在运行时对对象的方法和属性进行操作,有效的手段之一就是反射。这也是框架最常用的方法,因为框架不知道在编译时会使用系统中的哪些类。Java中对象的类型信息在运行时由Class对象表示,Class对象随着类加载而实例化,反射的实现围绕着Class对象。获取类的Class对象的方法有很多种,包括:Classc1=Object.class;Classc2=Class.forName("java.lang.Object");Classc3=newObject().getClass();反思能做什么?1.对象的实例化对象的实例化可以直接通过new关键字来实例化,也可以通过反射来实例化,例如:class.newInstance()class.getConstructor(Class...parameterTypes).newInstance(Object...initargs)为什么需要使用反射来实例化对象?存在不能直接使用new关键字实例化对象的场景,例如:Spring容器管理的Bean只能通过类的全限定名加载类,然后反射式实例化。在不想使用new关键字的场景下,目的是为了简化编程,让代码美观。你可能经常看到类似的用法,例如:publicstaticTparseObject(Stringtext,Classclazz){returnparseObject(text,clazz,newFeature[0]);}/***简单的复制出一个新类型的对象*/publicstaticDmap(Ssource,ClassdestinationClass){returnmapper.map(source,destinationClass);}2.筛选合适的类在实际开发中,经常会有这样的需求。如果一个类具有某些特征,则执行某些操作。Spring在扫描的时候,我们会通过过滤器精细控制bean的生成,包括:根据isInstance(Objectobj)判断是实现某个接口还是继承某个特殊的父类;判断是否使用isAnnotationPresent(ClassannotationClass)标注。3、方法调用在某些场景下,直接调用方法是不可能也不合适的。比如我们在处理HTTP请求时,需要从URI映射到方法调用。如果我们能够穷举所有的URLs和对象方法的映射关系,那是没有问题的,但是Countlessif条件判断显然不是一个明智的选择。通常我们先获取资源对象,然后反映调用该对象的方法。Method.invoke(Objectobj,Object...args)是如何得到对象的方法对象,即Method对象的呢?Class类提供如下实现:Method[]getMethods();Method[]getDeclaredMethods();MethodgetMethod(Stringname,Class...parameterTypes);MethodgetDeclaredMethod(Stringname,Class...parameterTypes);这些方法可以分为两类:签名中声明的方法会在当前类的所有方法中查找,但不会遍历父类。没有Declared的会遍历所有父类,但只会找public方法。推荐使用工具类:org.apache.commons.lang3.reflect.MethodUtils这个类包含了遍历所有父类搜索方法、当前类搜索公共方法或者反射执行方法的便捷操作。4.属性操作Class.getFields(),Class.getField(String),Class.getDeclaredFields(),Class.getDeclaredField(String)命名规则同方法,推荐使用工具类:org.apache。commons.lang3.FieldUtils,用于读取或赋值操作。通过反射赋值有几点需要注意:如果不是public类型,必须在设置字段前??通过Field.setAccessible(true)方法设置访问权限,否则会抛出异常抛出:非法访问异常。如果字段是静态类型,通过set方法赋值时会忽略obj对象,因为静态字段属于类。如果字段是final类型,不管是public还是private,在使用set方法赋值时,必须设置访问权限setAccessible后才能正确调用,否则会报异常:IllegalAccessException。但是当set方法赋值给final字段时,虽然方法调用正常,但是final字段的值并不会改变。如果该字段是最终静态类型,则在分配set方法时将始终抛出IllegalAccessException。最后,如果对当前对象的所有方法或字段进行某些操作,那么推荐工具类:org.springframework.util.ReflectionUtils4.总结所以反射其实并没有那么可怕。消除恐惧最好的方法就是直面恐惧,加油Let'slearn!