3.6、获取类的所有方法
修改实体类
/** * 基类 */ public class BaseClass { public String publicBaseVar1; public String publicBaseVar2; private void privatePrintBaseMsg(String var) { System.out.println("基类-私有方法,变量:" + var); } public void publicPrintBaseMsg(String var) { System.out.println("基类-公共方法,变量:" + var); } } /** * 子类 */ public class ChildClass extends BaseClass{ public String publicOneVar1; public String publicOneVar2; private String privateOneVar1; private String privateOneVar2; public String printOneMsg() { return privateOneVar1; } private void privatePrintOneMsg(String var) { System.out.println("子类-私有方法,变量:" + var); } public void publicPrintOneMsg(String var) { System.out.println("子类-公共方法,变量:" + var); } }
测试:
public class MethodTest { public static void main(String[] args) { //1.获取并输出类的名称 Class mClass = ChildClass.class; System.out.println("类的名称:" + mClass.getName()); System.out.println("----获取所有 public 访问权限的方法,包括自己声明和从父类继承的---"); //2 获取所有 public 访问权限的方法,包括自己声明和从父类继承的 Method[] mMethods = mClass.getMethods(); for (Method method : mMethods) { //获取并输出方法的访问权限(Modifiers:修饰符) int modifiers = method.getModifiers(); System.out.print(Modifier.toString(modifiers) + " "); //获取并输出方法的返回值类型 Class returnType = method.getReturnType(); System.out.print(returnType.getName() + " " + method.getName() + "( "); //获取并输出方法的所有参数 Parameter[] parameters = method.getParameters(); for (Parameter parameter : parameters) { System.out.print(parameter.getType().getName() + " " + parameter.getName() + ","); } //获取并输出方法抛出的异常 Class[] exceptionTypes = method.getExceptionTypes(); if (exceptionTypes.length == 0){ System.out.println(" )"); } else { for (Class c : exceptionTypes) { System.out.println(" ) throws " + c.getName()); } } } System.out.println("----获取所有本类的的方法---"); //3. 获取所有本类的的方法 Method[] allMethods = mClass.getDeclaredMethods(); for (Method method : allMethods) { //获取并输出方法的访问权限(Modifiers:修饰符) int modifiers = method.getModifiers(); System.out.print(Modifier.toString(modifiers) + " "); //获取并输出方法的返回值类型 Class returnType = method.getReturnType(); System.out.print(returnType.getName() + " " + method.getName() + "( "); //获取并输出方法的所有参数 Parameter[] parameters = method.getParameters(); for (Parameter parameter : parameters) { System.out.print(parameter.getType().getName() + " " + parameter.getName() + ","); } //获取并输出方法抛出的异常 Class[] exceptionTypes = method.getExceptionTypes(); if (exceptionTypes.length == 0){ System.out.println(" )"); } else { for (Class c : exceptionTypes) { System.out.println(" ) throws " + c.getName()); } } } } }
输出:
类的名称:com.example.java.reflect.ChildClass ----获取所有 public 访问权限的方法,包括自己声明和从父类继承的--- public java.lang.String printOneMsg( ) public void publicPrintOneMsg( java.lang.String arg0, ) public void publicPrintBaseMsg( java.lang.String arg0, ) public final void wait( long arg0,int arg1, ) throws java.lang.InterruptedException public final native void wait( long arg0, ) throws java.lang.InterruptedException public final void wait( ) throws java.lang.InterruptedException public boolean equals( java.lang.Object arg0, ) public java.lang.String toString( ) public native int hashCode( ) public final native java.lang.Class getClass( ) public final native void notify( ) public final native void notifyAll( ) ----获取所有本类的的方法--- public java.lang.String printOneMsg( ) private void privatePrintOneMsg( java.lang.String arg0, ) public void publicPrintOneMsg( java.lang.String arg0, )
为啥会输出这么多呢?
因为所有的类默认继承object类,打开object类会发现有些公共的方法,所以一并打印出来了!
3.7、调用方法
public class MethodInvokeTest { public static void main(String[] args) throws Exception { // 1.获取并输出类的名称 Class mClass = ChildClass.class; System.out.println("类的名称:" + mClass.getName()); System.out.println("----获取ChildClass类的私有方法privatePrintOneMsg---"); // 2. 获取对应的私有方法 // 第一个参数为要获取的私有方法的名称 // 第二个为要获取方法的参数的类型,参数为 Class...,没有参数就是null // 方法参数也可这么写 :new Class[]{String.class} Method privateMethod = mClass.getDeclaredMethod("privatePrintOneMsg", String.class); // 3. 开始操作方法 if (privateMethod != null) { // 获取私有方法的访问权 // 只是获取访问权,并不是修改实际权限 privateMethod.setAccessible(true); // 实例化对象 ChildClass obj = (ChildClass) mClass.newInstance(); // 使用 invoke 反射调用私有方法 // obj 要操作的对象 // 后面参数传实参 privateMethod.invoke(obj, "hello world"); } } }
输出结果:
类的名称:com.example.java.reflect.ChildClass ----获取ChildClass类的私有方法privatePrintOneMsg--- 子类-私有方法,变量:hello world
四、总结
由于反射会额外消耗一定的系统资源,因此如果不需要动态地创建一个对象,那么就不需要用反射。另外,反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。
五、参考文章
sczyh30:深入解析Java反射
伯特:Java 反射由浅入深