获取方法:
Class类中常用方法:
public Method[] getMethods();
-获取自身和继承过来的所有的public方法;
public Method[] getDeclaredMethods();
-获取自身所有的方法(不包括继承的,和访问权限无关)
public Method getMethod(String methodName,Class<?>... parameterTypes);
-表示调用指定的一个public的方法(包括继承的);
-参数:methodName,表示被调用方法的名字;
parameterTypes,表示被调用方法的参数的Class类型,如:String.class;
public Method getDeclaredMethod(String methodName,Class<?>... parameterTypes);
-表示调用指定的一个本来中的方法(不包括继承的);
调用方法
在Method类中
public Object invoke(Object obj, Object... args);
-表示调用当前Method所表示的方法。
参数:
obj:表示被调用方法底层所属对象;
Method m = clz.getMethod("sayHello",String.class);
args:表示调用方法时传递的实际参数;
返回:底层方法的返回结果。
*调用私有方法:
在调用私有方法之前应该何设置该方法为可访问的,又因为Method是AccessibleObject子类,所以Method类中具有该方法。
问题一答案:
Object obj = new java.util.Date();
Method method = obj.getClass().getMethod("toLocalString",String.class);
Object date = method.invoke(obj);
使用反射调用可变参数
使用反射调用静态方法:
静态方法不属于任何对象,属于类本身。
调用静态方法:
-把invoke()方法的第一个参数设置为null即可;
例如:
public class UseStaticMethod{
public static void main(String[] args){
Class<User> clzz = User.class;
Method m
=clzz.getMethod("doWork",String.class);
m.invoke(null,"无关风月");
}
}
class User{
public static void doWork(String name){
System.out.println("doWork(String name)被调用了"+"name = "+name);
}
}
设置为null处也可以设为方法所在类的对象,但其底层还是使用类调用,因此在运行时会被忽略该参数项,也就是说设置为任意对象都是可以运行成功的。
使用反射调用数组参数(可变参数):
-可变参数其底层就是一个数组。
使用反射调用方法的终极王道:
-调用方法时把实际参数统统作为Object[]的元素即可;
//使用反射调用可变参数(数组参数)
public class ArrayListArgs {
public static void main(String[] args) throws Exception {
Class<Employee> clazz = Employee.class;
// 情况一:数组的元素类型是基本类型
Method method = clazz.getMethod("doWork1", int[].class);
System.out.println(method);
// method.invoke(null,1,2,3,4,5,6); ERROR
method.invoke(null,new int[]{1,2,3,4,5});
// 情况二:数组的元素类型是引用类型
method = clazz.getMethod("doWork2", String[].class);
System.out.println(method);
// method.invoke(null,new String[]{"A","B","C"}); //ERROR
method.invoke(null,new Object[]{new String[]{"A","B","C"}});
// 对于引用类型会被自动解包,因此我们在传值是就得反向对其装包,使用Object[]封装一层;也适用于基本类型;
// 对于参数列表是泛型的如何调用
method = clazz.getMethod("toArray", Object[].class);
System.out.println(method);
}
}
class Employee{
public static void doWork1(int... args){//等价于int[] args
System.out.println("doWork1调用成功"+ Arrays.toString(args));
//System.out.println("可变参数调用成功"+ args); --打印的会是args的hashCode值;
}
public static void doWork2(String... args){//等价于int[] args
System.out.println("doWork2调用成功"+ Arrays.toString(args));
}
public <T> T[] toArray(T[] a) {
return null;
}
}
其他API
//反射其他相关API
public abstract class OtherApi {
public static void main(String[] args) {
// 获取修饰符
Class<OtherApi> clzz = OtherApi.class;
int mod = clzz.getModifiers();//返回类型为int?查看Modifier类中定义,十分巧妙的设计;
System.out.println(mod);
String s = Modifier.toString(mod);
System.out.println(s);
// 获取类名
System.out.println(clzz.getName());//com.reflection._2_methods.OtherApi
System.out.println(clzz.getSimpleName());//OtherApi
// 获取包名
System.out.println(clzz.getPackage());//package com.reflection._2_methods
System.out.println(clzz.getPackage().getName());//com.reflection._2_methods
// 获取父类名称
System.out.println(clzz.getSuperclass());//class java.lang.Object
System.out.println(clzz.getSuperclass().getName());//java.lang.Object
}
}
//对于枚举类,无法使用反射获取其信息,因为枚举类没有构造器;
enum Gender{
MAN,WOMAN,NONE;
}