前几天做单元测试,需要验证类的private方法。要想在一个类中执行另外一个类的private方法,只有下面两种方法:

    1.将private修改成public,不过这种会破坏类的封装;

    2.使用反射,通过方法名来执行private方法。

   一个简单的例子,如下:

public class MainClass {
    public static void main(String args[]){
        Person p = new Person();
        Class pClass = p.getClass();
        String methodName = "getInfo";
        Class[] parameterClass = new Class[]{int.class,String.class};
        Object result = null;
        try {
            Method method = pClass.getDeclaredMethod(methodName, parameterClass);
            method.setAccessible(true);   //值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查
            result = method.invoke(p, new Object[] { 35, "haha" });
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(null != result){
            String info = (String) result;
            System.out.println(info);
        }
    }
}

class Person{
    private String getInfo(int age,String name){
        return "name is: "+name +",age is: "+age;
    }
}

    但是,这样做会遇到一个问题。就是当你想通过反射执行从父类中继承的方法,会报异常 java.lang.NoSuchMethodException。
    这是,可以通过getSuperclass来获取父类的类对象,然后继续执行,代码如下:

public class MainClass {
    public static void main(String args[]){
        Father f = new Father();
        Class fClass = f.getClass();
        Class superClass = fClass.getSuperclass();
        String methodName = "getInfo";
        Class[] parameterClass = new Class[]{int.class,String.class};
        Object result = null;
        try {
            Method method = superClass.getDeclaredMethod(methodName, parameterClass);
            method.setAccessible(true);   //值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查
            result = method.invoke(f, new Object[] { 35, "haha" });
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(null != result){
            String info = (String) result;
            System.out.println(info);
        }
    }
}

class Person{
    private String getInfo(int age,String name){
        return "name is: "+name +",age is: "+age;
    }
}

class Father extends Person{
    
}

接下来,又产生了一个问题,有时候你并不想关心要执行的方法是不是从父类继续的。这时候,可以通过递归来得到Method对象。

public class MainClass {
    public static Method getMethod(Class classObj,String methodName,Class[] parameterClass){
        Method method = null;
        try {
            method = classObj.getDeclaredMethod(methodName, parameterClass);
        } catch (NoSuchMethodException e) {
            method = getMethod(classObj.getSuperclass(),methodName,parameterClass);
        }
        return method;
    }
    
    public static void main(String args[]){
        Father f = new Father();
        Class fClass = f.getClass();
        String methodName = "getInfo";
        Class[] parameterClass = new Class[]{int.class,String.class};
        Object result = null;
        try {
            Method method = getMethod(fClass,methodName,parameterClass);
            method.setAccessible(true);   //值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查
            result = method.invoke(f, new Object[] { 35, "haha" });
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(null != result){
            String info = (String) result;
            System.out.println(info);
        }
    }
}

class Person{
    private String getInfo(int age,String name){
        return "name is: "+name +",age is: "+age;
    }
}

class Father extends Person{

}