跳转到内容

使用反射访问私有特性

50% developed
来自 Wikibooks,开放的书籍,为开放的世界

浏览反射主题:v  d  e )

可以通过反射获取类的所有特性,包括访问private方法和变量。但并不总是如此,请参阅[1]。让我们看以下示例

Computer code 代码清单 10.3:Secret.java
public class Secret {
  private String secretCode = "It's a secret";
 
  private String getSecretCode() {
    return secretCode;     
  }
}

尽管字段和方法被标记为private,但以下类表明可以访问类的private特性

Computer code 代码清单 10.4:Hacker.java
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
public class Hacker {
 
   private static final Object[] EMPTY = {};
 
   public void reflect() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
     Secret instance = new Secret();
     Class<?> secretClass = instance.getClass();
 
     // Print all the method names & execution result
     Method methods[] = secretClass.getDeclaredMethods();
     System.out.println("Access all the methods");
     for (Method method : methods) {
        System.out.println("Method Name: " + method.getName());
        System.out.println("Return type: " + method.getReturnType());
        method.setAccessible(true);
        System.out.println(method.invoke(instance, EMPTY) + "\n");
     }
 
     // Print all the field names & values
     Field fields[] = secretClass.getDeclaredFields();
     System.out.println("Access all the fields");
     for (Field field : fields) {
        System.out.println("Field Name: " + field.getName());
        field.setAccessible(true);
        System.out.println(field.get(instance) + "\n");
     }
  }
 
  public static void main(String[] args) {
    Hacker newHacker = new Hacker();
 
    try {
      newHacker.reflect();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
Standard input or output 代码清单 10.4 的控制台
Access all the methods
Method Name: getSecretCode
Return type: class java.lang.String
It's a secret
Access all the fields
Field Name: secretCode
It's a secret
Clipboard

待办事项
我们需要添加一些关于这里发生了什么的解释。


JUnit - 测试私有方法

[编辑 | 编辑源代码]

JUnit 是单元测试用例,用于测试 Java 程序。现在您知道如何在 JUnit 中使用反射来测试私有方法。关于测试私有成员是否是一种好习惯存在长期争论[1];在某些情况下,您希望确保一个类表现出正确的行为,而不会将需要检查的字段设置为公有(因为通常将创建访问器仅仅为了单元测试被认为是不好的做法)。在其他情况下,您可以通过使用反射来测试所有较小的私有方法(以及它们的各种分支)来简化测试用例,然后测试主函数。使用dp4j [失效链接],可以测试私有成员,而无需直接使用反射 API,只需像从测试方法访问它们一样访问它们;dp4j 在编译时注入所需的反射代码[2]

  1. 单元测试私有方法的最佳方法是什么?,2011 年 3 月 7 日
  2. 编译时注入的反射 API [失效链接]


Clipboard

待办事项
添加一些类似于变量中练习的练习

华夏公益教科书