Java反射框架(二)——Field、Method

目录

3.Members

3.1Fields

3.2Methods

翻译源:Java toturial 反射篇


3.Members

3.1Fields

域是关联值的类、接口、枚举。

java.lang.reflect.Field中的方法可以检索域的信息,eg:名称、类型、修饰符、注解。有些方法还支持动态访问修改域值。

获取域名

String s = f.getName();

获取指定域

Field f = c.getField(fn);
Field f = c.getDeclaredField(fn);

获取所有域

Field[] flds = = c.getDeclaredFields();
Field[] fields = c.getFields();

获取域类型

Class c = f.getType();

note:返回表示Field对象f表示的域的类型的Class对象。

ps:如果类型为泛型,会受到类型擦除的影响。

Type t = f.getGenericType();

note:返回表示Field对象f表示的域的类性的Type对象。

ps:会从class文件的签名属性中读取类型信息,所以不会受到泛型的类型擦除机制的影响。

检索解析域修饰符

获取修饰符

int foundMods = f.getModifiers();

note:获取域f的修饰符集合。

ps:修饰符在java中的表现形式是Modifier中定义的静态常量,修饰符集合就是这些十六位int常量|操作之后的结果。

ps:可以使用Modifier解析这个int,获取域的所有修饰符信息。

判断域是否为合成域

boolean b = f.isSynthetic();

ps:合成域的意思是java编译器自动引入的域。

ps:内部类会自动引入合成域this$0,用于指向外部类。

ps:枚举类会自动引入合成域ENUM$VALUES。

ps:合成域由编译器决定,所以不同编译器可能会产生名称不同的合成域。

ps:合成域可以通过getDeclaredFields()获取。

判断域是否为枚举类型元素

boolean b = f.isEnumConstant();

ps:枚举类中的域皆是枚举类型元素。

判断域的修饰符是否包含给定修饰符

int searchMods = 0x0;
searchMods |= Modifier.PUBLIC;
int foundMods = f.getModifiers();
if((foundMods & searchMods) == searchMods) {
    ...				
}

note:如果域f为public,则执行if语句块。

Field实现了AnnotatedElement接口,所以可以获取持有的注解。

获取设置域值

获取原始类型域的值

long l = f.getLong(obj);

note:获取对象obj的long类型f域值l。

ps:getInt、getDouble、getFloat、getShort、getLong、getByte、getChar、getBoolean。

获取引用类型域的值

Object o = f.get(ft);

设置原始类型域的值

f.setLong(ftt, 33333);

note:将ftt对象的f域设置为33333,f域的类型为long。

ps:setInt、setDouble、setFloat、setShort、setLong、setByte、setChar、setBoolean。

设置引用类型域的值

f.set(ft, sss);

note:将ft对象的f域设置为对象sss,f域的类型为引用类型。

不能使用反射来修改final常量。

3.2Methods

反射代码将方法选择限定在一个特定类之中,而不考虑它的父类。

获取方法名

String s = m.getName();

获取指定方法

m = c.getMethod("run", int.class);
m = c.getDeclaredMethod("run", int.class);

ps:如果获取的方法的参数使用了泛型,使用java.lang.Object。

获取所有方法

Method[] allMethods = c.getMethods();
Method[] allMethods = c.getDeclaredMethods();

获取方法类型信息

获取方法名

String ss = m.toGenericString();

获取方法返回值类型

Class c = m.getReturnType();
Type t = m.getGenericReturnType();

ps:前者在遭遇泛型时,返回Object的Class,后者返回表示泛型参数的Type。

获取方法参数类型列表

Class<?>[] mty = m.getParameterTypes();
Type[] gty = m.getGenericParameterTypes();

ps:前者在遭遇泛型时,返回Object的Class,后者返回表示泛型参数的Type。

ps:如果获取的参数为可变参数,此参数返回一个组件类型为参数类型的数组的Class。

获取抛出异常列表

Class<?>[] ety = m.getExceptionTypes();
Type[] gety = m.getGenericExceptionTypes();

获取方法参数名

字节码文件默认不存储参数名称。

使用javac编译源代码时,使用-parameters选项可以将参数名称存入.class文件中,供反射机制获取。

使用java.lang.reflect.Parameter作为接口操作参数。

获取参数列表

Parameter[] ps = m.getParameters();

获取参数名称

String s = p.getName();

ps:如果没有设置javac的-parameters选项,根据参数列表顺序返回arg0、args1……

获取参数类型

Class c = p.getType();

获取参数修饰符

int m = p.getModifiers();

ps:可以使用Modifier.toString(),将得到的int表示的参数修饰符集合转变为可读字符串。

判断参数是否有名称

boolean b = p.isNamePresent();

判断参数是否为隐式参数

boolean b = p.isImplicit();

ps:java编译器会为内部类创建一个包含外部类引用参数的默认构造方法,此参数为隐式参数,此隐式参数为final与implicit。

判断参数是否为合成参数

boolean b = p.isSynthetic();

ps:编译器引入的没有在源代码中显式或隐式声明的结构,除了类初始化方法,都属于合成。

ps:Enum结构,默认由编译器创建构造器、values()、valueOf(String name)。

ps:合成方法内的参数皆是合成参数。

检索分析方法修饰符

获取方法修饰符

int mod = m.getModifiers();

判断方法是否含有变参

boolean b = m.isVarArgs();

note:包含返回true。

判断方法是否为桥接方法

boolean b = m.isBridge();

note:桥接方法返回true。

ps:桥接方法是,编译器在是实现泛型接口的类中,创建的以Object作为参数类型,并且调用实现类中的方法的中介方法。

ps:桥接方法就是一种合成方法。

判断方法是否为合成方法

boolean b = m.isSynthetic();

Method实现了AnnotatedElement接口,可以以此获取Method持有的注解。

调用方法

反射提供了调用类方法的API。

通常情况下,当不能类实例转化为需要的类型时,反射是调用方法的唯一途径。

反射调用方法

m.invoke(obj, null);

note:调用对象的Method对象m代表的无参方法。

ps:调用静态方法时,第一个参数传null。

ps:调用无参函数时,第一个参数之后的参数可以不传。

ps:方法的参数数量不定时,获取方法时使用数组类型的Class锁定方法,调用时传入数组。

ps:调用的方法如果为private,将会抛出异常。

ps:使用AccessibleObject.setAccessible()设置true,强制访问private。

获取反射调用方法抛出的异常

Throwable t = e.getCause();

ps:反射调用的方法抛出的异常会被反射框架的InvocationTargetException包装,通过getCause()方法可以获取原异常。

检验当前class与指定class是否相同,或是其父类

boolean b = YU.class.isAssignableFrom(TY.class);

note:检测YU是否与TY相同,或者YU为TY的父类。如果是,返回true。

ps:判断调用方法的Class代表的类型对象是否能给指定类型进行赋值,原理是父类对象可以让子类引用。


翻译源:Java toturial 反射篇

猜你喜欢

转载自blog.csdn.net/qq_32165041/article/details/82709260