Java反射——方法
使用Java反射,你可以检查类的方法并在运行时调用它们。这是通过Java类java.lang.reflect.Method做的。本将会比较详细的讲述Java的Method对象。下面是涵盖的主题列表:
Obtaining Method Objects (获取Method对象)
Method Parameters and Return Types (Method的参数和返回值类型)
Instantiating Objects using Constructor Object (使用构造函数对象实例化对象)
获取Method对象
从Class对象中获取Method对象。这里有个例子:
Class aClass = ...//obtain class object
Method[] methods = aClass.getMethods();
数组 methods 将存储类中声明的每个public方法的Method实例。
如果你知道你要访问的方法的准确的参数类型,你可以这样获取方法而不是所有的方法。
这个例子返回一个方法名叫doSomething的public的方法,在给定的类中指定了接受一个String类型的参数:
获取更加确切的方法
Class aClass = ...//obtain class object
Method method = aClass.getMethod("doSomething", new Class[]{String.class});
如果没有和给定参数相匹配的的方法,会抛出NoSuchMethodException异常。
获取无参数的方法
如果你尝试去访问的方法没有参数,传入null作为参数,像这样:
Class aClass = ...//obtain class object
Method method = aClass.getMethod("doSomething", null);
方法的入参和出参
入参
你可以像这样读取一个给定的方法所接收的参数:
Method method = ... // obtain method - see above
Class[] parameterTypes = method.getParameterTypes();
出参
你可以像这样访问一个方法的返回值类型:
Method method = ... // obtain method - see above
Class returnType = method.getReturnType();
调用方法
你可以像这样调用一个方法:
//get method that takes a String as argument
Method method = MyObject.class.getMethod("doSomething", String.class);
Object returnValue = method.invoke(null, "parameter-value1");
参数null是你想要调用方法的对象。如果是静态方法,你需要提供null作为参数而不是一个对象的实例。
在这个例子里,如果doSomething(String.class)不是静态的,你需要提供validMyObject作为实例而不是null。
方法 Method.invoke(Object target, Object … parameters)
接受不定个数的参数,但是你必须提供与你所调用的方法对应的每个参数。
在这里,这个方法接受一个String类型的参数,所以必须提供一个String类型的参数。
获取 Getter & Setter 方法
根据名称
使用Java反射你可以检查类的方法并在运行时调用它们。这个可以用来检测一个给定类所包含的Getter和Setter方法。你不能明确的获取Getter和Setter,所以你不得不通过扫描类里面的所有方法,然后检查每个方法是不是Getter方法或者Setter方法。
首先,让我们建立一些描述Getter和Setter特征的规则:
- Getter
一个getter方法的方法名易“get”开头,不接受参数,返回一个值。
- Setter
一个setter方法的方法名以“set”开头,接受一个参数。
setter方法既可以返回值也可以不返回值。
一些setter方法返回void,一些返回传入的值,其他的为了是使用方法链返回调用该setter的对象。
因此,你不应该对一个setter方法的返回值类型做假设。
这里是找出一个类的getter方法和setter方法的代码示例:
public static boolean isGetter(Method method){
if(!method.getName().startsWith("get")) return false;
if(method.getParameterTypes().length != 0) return false;
if(void.class.equals(method.getReturnType()) return false;
return true;
}
public static boolean isSetter(Method method){
if(!method.getName().startsWith("set")) return false;
if(method.getParameterTypes().length != 1) return false;
return true;
}
ps: 缺陷,比如 boolean 值得 get 方法,一般是 isXXX
根据类修饰符号
PropertyDescriptor 类信息。
public static void main(String[] args) throws Exception {
Class clazz = Class.forName("TaskProvidePropsList");//这里的类名是全名。。有包的话要加上包名
Object obj = clazz.newInstance();
Field[] fields = clazz.getDeclaredFields();
//写数据
for(Field f : fields) {
PropertyDescriptor pd = new PropertyDescriptor(f.getName(), clazz);
Method wM = pd.getWriteMethod();//获得写方法
wM.invoke(obj, 2);//因为知道是int类型的属性,所以传个int过去就是了。。实际情况中需要判断下他的参数类型
}
//读数据
for(Field f : fields) {
PropertyDescriptor pd = new PropertyDescriptor(f.getName(), clazz);
Method rM = pd.getReadMethod();//获得读方法
Integer num = (Integer) rM.invoke(obj);//因为知道是int类型的属性,所以转换成integer就是了。。也可以不转换直接打印
System.out.println(num);
}
}
}
私有方法
为了访问私有方法,你需要调用Class.getDeclaredMethod(String name, Class[] parameterTypes)方法或者Class.getDeclaredMethods()方法。
Class.getMethod(String name, Class[ ] parameterTypes)方法和Class.getMethods()只会返回共有的方法,所以它们不会工作。
下面是一个简单的代码示例,通过Java反射访问一个类的私有方法:
public class PrivateObject {
private String privateString = null;
public PrivateObject(String privateString) {
this.privateString = privateString;
}
private String getPrivateString(){
return this.privateString;
}
}
PrivateObject privateObject = new PrivateObject("The Private Value");
Method privateStringMethod = PrivateObject.class.getDeclaredMethod("getPrivateString", null);
privateStringMethod.setAccessible(true);
String returnValue = (String)privateStringMethod.invoke(privateObject, null);
System.out.println("returnValue = " + returnValue);
这段代码示例将会打印出文本“returnValue = The Private Value”,是在代码示例最开始创建的PrivateObject实例调用getPrivateString()方法时的返回值。
注意这里使用的方法PrivateObject.class.getDeclaredMethod(“privateString”)。是这个方法调用返回的私有方法。
这个方法只会返回在给定的类里面声明的方法,而不是在任何超类里声明的方法。
仅仅针对反射,通过调用 Method.setAccessible(true)
方法,关闭了对特定的Method实例的访问检查。
现在你可以访问它了,尽管它是private,或者protected,或者package scope,即使调用者不在这个范围内。你仍然不能通过一般的代码访问这些方法。编译器不允许这样干。
参考资料
http://tutorials.jenkov.com/java-reflection/index.html
https://www.cnblogs.com/jason123/p/7092008.html