盡管普遍認(rèn)為通過Java Reflection可以訪問其他類的私有字段和方法。 這并不困難。 這在單元測(cè)試中可以非常方便。 本文將告訴你如何。
訪問私有字段
要訪問私有字段,您需要調(diào)用Class.getDeclaredField(String name)或Class.getDeclaredFields()方法。 方法Class.getField(String name)和Class.getFields()方法只返回公共字段,所以它們將不起作用。 下面是一個(gè)帶有私有字段的類的簡(jiǎn)單例子,下面是通過Java反射訪問該字段的代碼:
public class PrivateObject {
private String privateString = null;
public PrivateObject(String privateString) {
this.privateString = privateString;
}
}
PrivateObject privateObject = new PrivateObject("The Private Value");
Field privateStringField = PrivateObject.class.
getDeclaredField("privateString");
//關(guān)閉對(duì)此特定字段實(shí)例的訪問檢查
privateStringField.setAccessible(true);
String fieldValue = (String) privateStringField.get(privateObject);
System.out.println("fieldValue = " + fieldValue);
此代碼示例將打印出“fieldValue = The Private Value”文本,該文本是在代碼示例開始時(shí)創(chuàng)建的PrivateObject實(shí)例的private字段privateString的值。
注意使用PrivateObject.class.getDeclaredField(“privateString”)方法。 這是這個(gè)方法調(diào)用返回私人字段。 此方法只返回在該特定類中聲明的字段,而不是在任何超類中聲明的字段。
注意粗線也是。 通過調(diào)用Field.setAccessible(true),可以關(guān)閉對(duì)此特定字段實(shí)例的訪問檢查,僅用于反射。 現(xiàn)在,即使調(diào)用者不是這些范圍的一部分,即使它是私有的,受保護(hù)的或包的范圍,也可以訪問它。 您仍然無法使用正常代碼訪問該字段。 編譯器不會(huì)允許它。
訪問私有方法
要訪問私有方法,您將需要調(diào)用Class.getDeclaredMethod(String name,Class [] parameterTypes)或Class.getDeclaredMethods()方法。 方法Class.getMethod(String name,Class [] parameterTypes)和Class.getMethods()方法只返回公共方法,所以它們將不起作用。 下面是一個(gè)帶私有方法的類的簡(jiǎn)單示例,下面是通過Java反射訪問該方法的代碼:
public class PrivateObject {
private String privateString = null;
public PrivateObject(String privateString) {
this.privateString = privateString;
}
private String getPrivateString(){
return this.privateString;
}
}
PrivateObject privateObject = new PrivateObject("The Private Value");
Method privateStringMethod = PrivateObject.class.
getDeclaredMethod("getPrivateString", null);
privateStringMethod.setAccessible(true);
String returnValue = (String)
privateStringMethod.invoke(privateObject, null);
System.out.println("returnValue = " + returnValue);
此代碼示例將在代碼示例的開頭處創(chuàng)建的PrivateObject實(shí)例上調(diào)用時(shí),打印出文本“returnValue = The Private Value”,這是getPrivateString()方法返回的值。
注意使用PrivateObject.class.getDeclaredMethod(“privateString”)方法。 正是這個(gè)方法調(diào)用返回私有方法。
通過調(diào)用Method.setAccessible(true),可以關(guān)閉此特定Method實(shí)例的訪問檢查,僅用于反射。 現(xiàn)在,即使調(diào)用者不是這些范圍的一部分,即使它是私有的,受保護(hù)的或包的范圍,也可以訪問它。 您仍然無法使用普通代碼訪問該方法。 編譯器不會(huì)允許它。
實(shí)戰(zhàn)
package com.reflection.detail;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Created by Fant.J.
* 2018/2/7 15:28
*/
public class Reflection_Private {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//獲取對(duì)象
Class aClass = People.class;
Field privateField = aClass.getDeclaredField("privateString");
//設(shè)置允許jvm編譯通過。(jvm 默認(rèn)不允許訪問 私有類型的東西)
privateField.setAccessible(true);
//獲取私有字段的值
People people = new People();
Object privateStringResult = privateField.get(people);
System.out.println(privateStringResult);
//獲取私有方法
//獲取setPrivateString方法
Method privateMethod = aClass.getDeclaredMethod("setPrivateString", String.class);
//獲取getPrivateString方法
Method privateMethod1 = aClass.getDeclaredMethod("getPrivateString", null);
//jvm編譯通過允許
privateMethod.setAccessible(true);
//反射對(duì)象和參數(shù) 給setPrivateString方法
privateMethod.invoke(people,"Fant.J is so cool");
//反射對(duì)象和參數(shù) 給getPrivateString方法
Object obj = privateMethod1.invoke(people,null);
System.out.println(obj);
}
}
package com.reflection.detail;
/**
* Created by Fant.J.
* 2018/2/7 14:37
*/
public class People {
private Integer id;
private String name;
//field 字段
public String someField = "FantJ";
private String privateString = "shuai";
public People(Integer id, String name) {
this.id = id;
this.name = name;
}
public String getSomeField() {
return someField;
}
public void setSomeField(String someField) {
this.someField = someField;
}
public String getPrivateString() {
return privateString;
}
public void setPrivateString(String privateString) {
this.privateString = privateString;
}
public People(){}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
shuai
Fant.J is so cool
項(xiàng)目代碼:github鏈接