回顾:
Class 对象:在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。
Class对象获取的三种法法:
//方法一:Class class对象名 = 类名.class
Class cls1 = String.class;
//方法二:Class class对象名 = 对象.getClass()
String s = "chengyuan";
Class cls2 = s.getClass();
//方法三:Class class对象名 = Class.forName("类名");
Class cls3 = Class.forName("java.lang.String");
本文重点:
1 通过Class实例来获取Method对象:
Method getMethod("方法名"); //返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
Method getDeclaredMethod("方法名"); //返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
Method[] getMethods(); //返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。
Method[] getDeclaredMethods(); //返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
2 通过Method对象,得到有关于该方法的信息:
Class<?> getReturnType(); //返回一个 Class 对象,该对象描述了此 Method 对象所表示的方法的正式返回类型。
Class<?>[] getParameterTypes(); //按照声明顺序返回 Class 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型。
int getModifiers(); //以整数形式返回此 Method 对象所表示方法的 Java 语言修饰符。
String getName(); //以 String 形式返回此 Method 对象表示的方法名称。
3 通过Method对象调用方法
Object invoke(Object obj [,Object... args]) //对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
4 反射实现多态:从父类.class获取的Method对象,调用时参数一传递的是子类对象是实际上调用的还是子类的重写方法,与多态性保持一致
5 通过Method对象调用 setAccessible(boolean flag)方法,实现对方法的修饰符更改,例如把private修饰的方法,改成public修饰,从而实现反射调用,但是并非所有的方法都可以修改,若是该方法定义了securityManager规则则会阻止修改
下面用代码一一演示:
public class ReflectionMethod {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Person p = new Person();
//通过反射获取Person类的方法
//得到Person类的hello方法的Method对象
Method methodHello = p.getClass().getMethod("hello");
//得到Person类的私有化的sayHi方法的Method对象
Method methodSay = p.getClass().getDeclaredMethod("sayHi",String.class);
/* 得到所有的public方法包含父类 */
Method[] methods = p.getClass().getMethods();
//得到所有的方法对象含有私有化的,不含父类的
Method[] methodsAll = p.getClass().getDeclaredMethods();
//通过Method对象,得到有关于该方法的信息
System.out.println("方法返回值类型:" + methodHello.getReturnType());
System.out.println("方法修饰符:" + methodHello.getModifiers());
System.out.println("方法参数类型:" +methodSay.getParameterTypes()[0]);
System.out.println("方法名:" +methodSay.getName());
System.out.println("方法调用+++++++++++++++++++++");
//调用p对象的无参数hello方法
methodHello.invoke(p);
//调用p对象的有参数sayHi方法
//由于say是私有方法不能直接调用,所以要打破封装性
methodSay.setAccessible(true);
methodSay.invoke(p,"悦影");
System.out.println("反射多态一致性+++++++++++++++++");
//反射多态一致性
Teacher tea = new Teacher();
Person.class.getMethod("hello").invoke(tea); //"Teacher:hello"
}
}
class Person{
public void hello(){
System.out.println("Person:hello");
}
private void sayHi(String name){
System.out.println("Hi, "+name);
}
}
class Teacher extends Person{
@Override
public void hello(){
System.out.println("Teacher:hello");
}
}