记录:481
场景:java.lang.reflect.Method的使用,包括但不限于创建Method对象,使用Method对象的invoke方法调用类方法,使用Method对象获取方法上的注解,以及其它常用方式使用。在Java反射机制中发挥重要作用。
版本:JDK 1.8,Spring Boot 2.6.3。
1.基础
1.1Method类
在JDK的java.lang.reflect.Method中对Method的官方说明如下:
A Method provides information about, and access to, a single method on a class or interface. The reflected method may be a class method or an instance method (including an abstract method).
A Method permits widening conversions to occur when matching the actual parameters to invoke with the underlying method's formal parameters, but it throws an IllegalArgumentException if a narrowing conversion would occur.
1.2Java 反射机制
Java 反射机制是在运行状态中,对于任意一个类,都能够获得这个类的所有属性和方法,对于任意一个对象都能够调用它的任意一个属性和方法。这种在运行时动态的获取信息以及动态调用对象的方法的功能称为Java 的反射机制。
2.创建Method对象
使用类的Class对象获取该类的Method对象。public修饰的方法使用getMethod和getMethods获取Method对象。使用getDeclaredMethod和getDeclaredMethods获取类所有声明的方法的Method对象。
Class<?> clz01 = Worker.class;
//1.获取类的方法(public修饰的方法)
Method[] method01 = clz01.getMethods();
Method method02 = clz01.getMethod("getCityInfo", String.class);
StringBuilder sb01 = new StringBuilder();
Arrays.asList(method01).forEach(item -> {
sb01.append(item.getName() + ",");
});
System.out.println("method01方法列表: " + sb01.toString());
System.out.println("method02方法名称: " + method02.getName());
//2.获取类的声明方法(public/protected/private)
Method[] method03 = clz01.getDeclaredMethods();
Method method04 = clz01.getDeclaredMethod("getCountryInfo", String.class);
StringBuilder sb02 = new StringBuilder();
Arrays.asList(method03).forEach(item -> {
sb02.append(item.getName() + ",");
});
System.out.println("method03方法列表: " + sb02.toString());
System.out.println("method04方法名称: " + method04.getName());
//3.获取类的闭合方法
Class<?> clz02 = (new FujianProvince01()).work().getClass();
Method method05 = clz02.getEnclosingMethod();
3.使用Method对象的invoke方法调用类方法
使用Method对象的invoke方法调用类方法。在反射中就是使用此方法。
Class<?> clz03 = Worker.class;
//1.使用Method对象调用类的private修饰的方法(需设置允许访问)
Method method06 = clz03.getDeclaredMethod("getCountryInfo", String.class);
method06.setAccessible(true);
Object obj01 = method06.invoke(clz03.newInstance(), "中国");
System.out.println("obj01 = " + obj01.toString());
//2.使用Method对象调用类的protected修饰的方法(需设置允许访问)
Method method07 = clz03.getDeclaredMethod("getProvinceInfo", String.class);
method07.setAccessible(true);
Object obj02 = method07.invoke(clz03.newInstance(), "350000");
System.out.println("obj02 = " + obj02.toString());
//3.使用Method对象调用类的public修饰的方法
Method method08 = clz03.getDeclaredMethod("getCityInfo", String.class);
Object obj03 = method08.invoke(clz03.newInstance(), "350200");
System.out.println("obj03 = " + obj03.toString());
//4.使用Method对象调用类的public修饰的方法
Method method09 = clz03.getDeclaredMethod("getDistrictInfo", String.class);
Object obj04 = method09.invoke(clz03.newInstance(), "350203");
System.out.println("obj04 = " + obj04.toString());
4.使用Method对象获取方法上的注解
使用Method对象获取方法上的注解,在反射编程和面向切片编程时,起到重要作用:
Class<?> clz04 = Worker.class;
Method method10 = clz04.getDeclaredMethod("getDistrictName", String.class);
Annotation anno01 = method10.getAnnotation(DistrictMethodAno.class);
Annotation[] anno02 = method10.getAnnotations();
Annotation anno03 = method10.getDeclaredAnnotation(DistrictMethodAno.class);
Annotation[] anno04 = method10.getDeclaredAnnotations();
Annotation[][] anno05 = method10.getParameterAnnotations();
Annotation[] anno06 = method10.getAnnotationsByType(DistrictMethodAno.class);
AnnotatedType anno07 = method10.getAnnotatedReceiverType();
AnnotatedType[] anno08 = method10.getAnnotatedParameterTypes();
AnnotatedType anno09 = method10.getAnnotatedReturnType();
AnnotatedType[] anno10 = method10.getAnnotatedExceptionTypes();
Annotation[] anno11 = method10.getDeclaredAnnotationsByType(DistrictMethodAno.class);
5.其它常用方法
Class<?> clz05 = Worker.class;
Method method11 = clz04.getDeclaredMethod("getCityInfo", String.class);
//获取方法名称
String name01 = method11.getName();
//获取Modifier
int mod01 = method11.getModifiers();
//参数类型
TypeVariable<Method>[] type01 = method11.getTypeParameters();
//返回值类型
Class<?> clz06 = method11.getReturnType();
Type type02 = method11.getGenericReturnType();
//参数类型
Class<?>[] clz07 = method11.getParameterTypes();
//参数个数
int num01 = method11.getParameterCount();
//参数类型
Type[] type03 = method11.getGenericParameterTypes();
//异常类型
Class<?>[] clz08 = method11.getExceptionTypes();
Type[] type04 = method11.getGenericExceptionTypes();
//Hash编码
int num02 = method11.hashCode();
//判断方法
boolean bl01 = method11.isBridge();
boolean bl02 = method11.isVarArgs();
boolean bl03 = method11.isSynthetic();
boolean bl04 = method11.isDefault();
Object obj05 = method11.getDefaultValue();
6.辅助类
6.1DistrictMethodAno注解
注解DistrictMethodAno作用在方法上。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DistrictMethodAno {
//区编码
String code();
//区名称
String value() default "";
}
6.2ReturnAno注解
作用在返回值上的注解。
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ReturnAno {
}
6.3ParameterAno注解
作用在参数上的注解。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface ParameterAno {
//参数编码
String code();
//参数名称
String value() default "";
}
6.4Worker测试类
在Worker中定义了几种类型方法,使用Method对象调用。
public class Worker {
public String name;
private String getCountryInfo(String name) {
if (StringUtils.equals("中国", name))
return "中国是一个了不起的国家";
return "请检查输入的国名";
}
protected String getProvinceInfo(String code) {
if (StringUtils.equals("350000", code))
return "福建是一个沿海省";
return "请检查省级行政区编码";
}
public String getCityInfo(String code) {
if (StringUtils.equals("350200", code))
return "厦门是一个美丽城市";
return "请检查市级行政区编码";
}
public static String getDistrictInfo(String code) {
if (StringUtils.equals("350203", code))
return "思明区在厦门岛内";
return "请检查区级行政区编码";
}
@DistrictMethodAno(code = "Haicang",value = "海沧区")
public @ReturnAno String getDistrictName(@ParameterAno(code = "01",value = "区名称") String code) {
if (StringUtils.equals("350205", code))
return "海沧区";
return "请检查区级行政区编码";
}
}
6.5FujianProvince01测试类
在FujianProvince01的方法中定义了类。
public class FujianProvince01 {
public Object city;
//构造方法内定义类
public FujianProvince01() {
class Xiamen {
public String cityNo;
public String cityName;
}
city = new Xiamen();
}
//方法内定义类
public Object work() {
class Haicang {
public String cityNo = "350203";
public String cityName = "思明区";
public String getDistrictInfo(String code) {
if (StringUtils.equals(cityNo, code))
return cityName + "在厦门岛内";
return "请检查区级行政区编码";
}
}
return new Haicang();
}
}
以上,感谢。
2024年3月1日