JAVA反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意方法和屬性;這種動態獲取信息以及動態調用對象方法的功能稱爲java語言的反射機制。
在日常開發過程中,會遇到某個類的某個成員變量、方法或是屬性是私有的或是隻對系統應用開放,這時候就可以利用Java的反射機制通過反射來獲取所需的私有成員或是方法。比如JDBC鏈接:
Class.forName("com.mysql.cj.jdbc.Driver");
反射機制的相關類
Class代表類的實例,表示正在運行的Java應用程序中的類和接口。Class沒有公共構造函數。相反,Class對象由Java虛擬機在加載類時自動構造,並通過調用類加載器中的defineClass方法來構造。
類名
public final class Class<T>
implements java.io.Serializable,
GenericDeclaration,
Type,
AnnotatedElement
在Class中有個靜態代碼塊,此native方法表示向JVM註冊本地方法。
private static native void registerNatives();
static {
registerNatives();
}
forName(String className)
@CallerSensitive
public static Class<?> forName(String className)
throws ClassNotFoundException {
//返回調用這個方法的類對象
Class<?> caller = Reflection.getCallerClass();
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}
返回給定字符串名稱的類或接口關聯的類對象,@CallerSensitive爲了防止通過構造雙重反射來提升權限。
T newInstance()
@CallerSensitive
public T newInstance()
throws InstantiationException, IllegalAccessException
{
if (System.getSecurityManager() != null) {
//檢查是否允許訪問成員。如果拒絕訪問,則拋出SecurityException
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
}
// Constructor lookup
if (cachedConstructor == null) {
if (this == Class.class) {
throw new IllegalAccessException(
"Can not call newInstance() on the Class for java.lang.Class"
);
}
try {
Class<?>[] empty = {};
//先獲得Constructor數組,拿到所有的構造,包括非public的
final Constructor<T> c = getConstructor0(empty, Member.DECLARED);
// 禁用構造函數的可訪問性檢查
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
c.setAccessible(true);
return null;
}
});
cachedConstructor = c;
} catch (NoSuchMethodException e) {
throw (InstantiationException)
new InstantiationException(getName()).initCause(e);
}
}
Constructor<T> tmpConstructor = cachedConstructor;
int modifiers = tmpConstructor.getModifiers();
//檢查是否是public,如果是public,返回true
if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
if (newInstanceCallerCache != caller) {
Reflection.ensureMemberAccess(caller, this, null, modifiers);
newInstanceCallerCache = caller;
}
}
// Run constructor
try {
//創建並初始化具有指定初始化參數的構造函數的聲明類的新實例
return tmpConstructor.newInstance((Object[])null);
} catch (InvocationTargetException e) {
Unsafe.getUnsafe().throwException(e.getTargetException());
// Not reached
return null;
}
}
栗子:
public class Student implements Serializable {
private static final long serialVersionUID = -1L;
private String id;
private String name;
public Integer age;
public Student(){}
public Student(String id, String name) {
this.id = id;
this.name = name;
}
private int sum(int i, int j){
return i + j;
}
public Student getStudent(int id){
return this;
}
public Student getStudent(String name){
return new Student();
}
public String getInfo(){
return id + " " + name;
}
}
Student student = Student.class.newInstance();
但是在jdk9以上,這個方法被棄用了,而使用下面的方法:
Student student =
Student.class.getDeclaredConstructor().newInstance()
getMethods()
@CallerSensitive
public Method[] getMethods() throws SecurityException {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
return copyMethods(privateGetPublicMethods());
}
返回一個數組,該數組包含Method對象,這些對象包含該class對象表示的類或接口的所有公共方法,包括由該類或接口聲明的方法以及從父類和父接口繼承的方法。裏面調用了privateGetPublicMethods方法
private Method[] privateGetPublicMethods() {
checkInitted();
Method[] res;
ReflectionData<T> rd = reflectionData();
if (rd != null) {
res = rd.publicMethods;
if (res != null) return res;
}
//沒有可用的緩存值;遞歸計算值。從獲取公共聲明的方法開始
MethodArray methods = new MethodArray();
{
Method[] tmp = privateGetDeclaredMethods(true);
methods.addAll(tmp);
}
// 首先檢查父接口,這樣我們可以更容易地過濾掉最後從父類繼承的具體實現。
MethodArray inheritedMethods = new MethodArray();
for (Class<?> i : getInterfaces()) {
inheritedMethods.addInterfaceMethods(i.privateGetPublicMethods());
}
if (!isInterface()) { //如果不是接口
Class<?> c = getSuperclass();//得到父類
if (c != null) {
MethodArray supers = new MethodArray();
//父類中的public方法
supers.addAll(c.privateGetPublicMethods());
// 過濾掉任何接口方法的具體實現
for (int i = 0; i < supers.length(); i++) {
Method m = supers.get(i);
if (m != null &&
!Modifier.isAbstract(m.getModifiers()) &&
!m.isDefault()) {
inheritedMethods.removeByNameAndDescriptor(m);
}
}
// 在父接口之前插入父類的繼承方法以滿足getMethod的搜索順序
supers.addAll(inheritedMethods);
inheritedMethods = supers;
}
}
// 從繼承的方法中篩選出所有本地方法
for (int i = 0; i < methods.length(); i++) {
Method m = methods.get(i);
inheritedMethods.removeByNameAndDescriptor(m);
}
methods.addAllIfNotPresent(inheritedMethods);
methods.removeLessSpecifics();
methods.compactAndTrim();
res = methods.getArray();
if (rd != null) {
rd.publicMethods = res;
}
return res;
}
與getMethods()方法對應的還有一個getDeclaredMethods(),這個方法返回一個Method對象數組,其中包含該Class對象表示的類或接口的所有已聲明方法,包括public、protected、default(package)訪問和private方法,但不包括繼承的方法。
@CallerSensitive
public Method[] getDeclaredMethods() throws SecurityException {
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
return copyMethods(privateGetDeclaredMethods(false));
}
private Method[] privateGetDeclaredMethods(boolean publicOnly) {
checkInitted();
Method[] res;
ReflectionData<T> rd = reflectionData();
if (rd != null) {
res = publicOnly ? rd.declaredPublicMethods : rd.declaredMethods;
if (res != null) return res;
}
//getDeclaredMethods0底層方法獲取本類方法
res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly));
if (rd != null) {
if (publicOnly) {
rd.declaredPublicMethods = res;
} else {
rd.declaredMethods = res;
}
}
return res;
}
getFields()
@CallerSensitive
public Field[] getFields() throws SecurityException {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
return copyFields(privateGetPublicFields(null));
}
返回一個包含Field對象的數組,該數組包含Class對象表示的類或接口的所有可訪問公共字段。包括父類和父接口的公共字段。調用的privateGetPublicFields方法如下:
private Field[] privateGetPublicFields(Set<Class<?>> traversedInterfaces) {
checkInitted();
Field[] res;
ReflectionData<T> rd = reflectionData();
if (rd != null) {
res = rd.publicFields;
if (res != null) return res;
}
List<Field> fields = new ArrayList<>();
if (traversedInterfaces == null) {
traversedInterfaces = new HashSet<>();
}
// 類本身的字段
Field[] tmp = privateGetDeclaredFields(true);
addAll(fields, tmp);
// 遍歷父接口
for (Class<?> c : getInterfaces()) {
if (!traversedInterfaces.contains(c)) {
traversedInterfaces.add(c);
addAll(fields, c.privateGetPublicFields(traversedInterfaces));
}
}
// 父類
if (!isInterface()) {
Class<?> c = getSuperclass();
if (c != null) {
addAll(fields, c.privateGetPublicFields(traversedInterfaces));
}
}
res = new Field[fields.size()];
fields.toArray(res);
if (rd != null) {
rd.publicFields = res;
}
return res;
}
getFields()也有一個對應的方法getDeclaredFields(),這個方法返回Field對象的數組,該數組包含該Class對象表示的類或接口聲明的所有字段。這包括公共、受保護、默認(包)訪問和私有字段,但不包括繼承字段。
@CallerSensitive
public Field[] getDeclaredFields() throws SecurityException {
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
return copyFields(privateGetDeclaredFields(false));
}
private Field[] privateGetDeclaredFields(boolean publicOnly) {
checkInitted();
Field[] res;
ReflectionData<T> rd = reflectionData();
if (rd != null) {
res = publicOnly ? rd.declaredPublicFields : rd.declaredFields;
if (res != null) return res;
}
// 調用底層方法
res = Reflection.filterFields(this, getDeclaredFields0(publicOnly));
if (rd != null) {
if (publicOnly) {
rd.declaredPublicFields = res;
} else {
rd.declaredFields = res;
}
}
return res;
}
getResourceAsStream(String name)
public InputStream getResourceAsStream(String name) {
//如果名稱不是絕對的,則添加包名稱前綴如果名稱是絕對的,則刪除前導“/”
name = resolveName(name);
ClassLoader cl = getClassLoader0();
if (cl==null) {
// A system class.
return ClassLoader.getSystemResourceAsStream(name);
}
return cl.getResourceAsStream(name);
}
此方法查找具有給定名稱的資源。搜索與給定類關聯的資源的規則是通過定義類的ClassLoader來實現的。此方法委託給此對象的類加載器。如果此對象是由引導類加載器加載的,則方法將委託給getSystemResourceAsStream。如果name以'/'開頭,則資源的絕對名稱是'/'後面的部分。如果名稱不是絕對的,則添加包名稱前綴,如果名稱是絕對的,則刪除前導“/”。
InputStream resourceAsStream =
Student.class.getResourceAsStream("application.xml");
更多精彩內容請關注微信公衆號: