深入分析Java反射(一)-核心类库和方法 (9)

关注其中的invoke(Object obj, Object... args)方法,第一个是要调用这个方法的对象,剩下的方法的参数,返回值就是该方法执行的返回值。如果方法的修饰符不是public,在调用invoke方法前需要调用setAccessible(boolean flag)抑制方法访问修饰符的权限判断,否则会抛出异常。举个例子如下:

public class Main10 { public static void main(String[] args) throws Exception{ Class<Supper> supperClass = Supper.class; Supper supper = supperClass.newInstance(); Method sayHello = supperClass.getDeclaredMethod("sayHello", String.class); sayHello.setAccessible(Boolean.TRUE); sayHello.invoke(supper,"throwable"); } public static class Supper{ private void sayHello(String name){ System.out.println(String.format("%s say hello!", name)); } } }

输出结果:

throwable say hello! Field类

Field类用来描述一个类里面的属性或者叫成员变量,通过Field可以获取属性的注解信息、泛型信息,获取和设置属性的值等等。Field的主要方法如下:

方法 功能
String getName()   返回该属性的名称  
int getModifiers()   返回该属性的修饰符  
Class<?> getType()   返回该属性的类型Class  
Class<?> getParameterizedType()   返回该属性的泛型类型Type  
boolean isSynthetic()   该属性是否复合的  
boolean isEnumConstant()   该属性是否枚举类型的元素  
Object get(Object obj)   通过对象实例获取该属性的值  
void set(Object obj,Object value)   通过对象实例设置该属性的值  
void setAccessible(boolean flag)   抑制属性访问修饰符的权限判断  

这里忽略了注解以及Field实现了FieldAccessor接口中的getBoolean、setBoolean等方法。下面举个例子说明一下Field的用法:

public class Main12 { public static void main(String[] args) throws Exception { Class<Supper> supperClass = Supper.class; Supper supper = supperClass.newInstance(); Method sayHello = supperClass.getDeclaredMethod("sayHello"); sayHello.setAccessible(Boolean.TRUE); Field name = supperClass.getDeclaredField("name"); name.setAccessible(Boolean.TRUE); name.set(supper,"throwable"); System.out.println("Field get-->" + name.get(supper)); sayHello.invoke(supper); name.set(supper, "throwable-10086"); System.out.println("Field get-->" + name.get(supper)); sayHello.invoke(supper); } public static class Supper { private String name; private void sayHello() { System.out.println(String.format("%s say hello!", name)); } } }

输出结果:

Field get-->throwable throwable say hello! Field get-->throwable-10086 throwable-10086 say hello! Parameter类

Parameter用于描述Method或者Constructor的参数,主要是用于获取参数的名称。因为在Java中没有形式参数的概念,也就是参数都是没有名称的。Jdk1.8新增了Parameter用来填补这个问题,使用javac编译器的时候加上-parameters参数的话,会在生成的.class文件中额外存储参数的元信息,这样会导致.class文件的大小增加。当你输入javac -help的时候,你会看到-parameters这个选项。获取Parameter的方法是Method或者Constructor的父类Executable的getParamaters方法。一般而言,Parameter是用于获取参数名称的后备方案,因为Jdk1.8之前没有这个类,并且即使使用了Jdk1.8如果javac编译器的时候没有加上-parameters参数的话,通过Parameter获取到的参数名称将会是"arg0"、"arg1"..."argn"类似的没有意义的参数名称。一般框架中使用其他方法解析方法或者构造器的参数名称,参考Spring的源码,具体是LocalVariableTableParameterNameDiscoverer,是使用ASM去解析和读取类文件字节码,提取参数名称。Parameter的主要方法如下:

方法 功能
String getName()   返回该参数的名称  
int getModifiers()   返回该参数的修饰符  
Class<?> getType()   返回该参数的类型Class  
Class<?> getParameterizedType()   返回该参数的泛型类型Type  
boolean isNamePresent()   该参数的名称是否保存在class文件中,需要编译时加参数-parameters  
boolean isImplicit()   该参数是否隐式声明  
boolean isSynthetic()   该参数是否复合的  
boolean isVarArgs()   该参数是否不定参数  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zywspx.html