Class (反射的入口)、Method (成員方法)、Field (成員變量)java
java反射經常使用的一些實例ide
package cn.com; import java.lang.reflect.Method; /** * Copyright (C), 2018-2019 * * @Description: TODO * @Author: zhou * @Create: 2019/10/10 16:36 * @Version 1.0.0 */ public class MethodInvoke { public static void main(String[] args) throws Exception { Class implClass = Class.forName("cn.com.Animal"); Object instance = implClass.newInstance(); // 實例 System.out.println("instance:" + instance); Method method = instance.getClass().getMethod("print"); method.invoke(instance); Method method1 = implClass.getDeclaredMethod("print"); method1.invoke(instance);
// 訪問是有方法 printS
Method privteMethod = implClass.getDeclaredMethod("printS");
privteMethod.setAccessible(true); //設置或取消訪問檢查,以達到訪問私有對象的目的。
privteMethod.invoke(instance);
Method animalMethod = Animal.class.getDeclaredMethod("print"); Method catMethod = Cat.class.getDeclaredMethod("print"); Animal animal = new Animal(); Cat cat = new Cat(); animalMethod.invoke(cat); animalMethod.invoke(animal); System.out.println("====="); catMethod.invoke(cat); catMethod.invoke(animal); } } class Animal { public void print() { System.out.println("Animal.print()"); }
private void printS(){
System.out.println("Animal.privateFunction");
}
}
class Cat extends Animal { @Override public void print() { System.out.println("Cat.print()"); } }
獲取反射的方法有:ui
第一種:
Class animal =Animal.class;
第二種:
Class animal = Class.forName("cn.com.Animal"); // Animal類的全路徑
獲取到 Class 以後,即可以獲取有參方法
Method method = animal.getDeclaredMethod(String name, Class<?>... parameterTypes);
Method method = animal.getMethod(String name, Class<?>... parameterTypes);
其中: name 爲方法名,paramterTypers方法的參數類型
能夠經過 Object instance = animal.newInstance(); 將類實例化
最後經過
method.invoke(instance, parameValue);
instance爲類是實例化,paramValue爲方法參數(根據實際狀況傳入)
java反射可饒過不能訪問私有方法的限制,須要添加
setAccessible(true); //設置或取消訪問檢查,以達到訪問私有對象的目的。
接下來,咱們來看看invoke()方法的實現過程。
@CallerSensitive public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { if (!override) { if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { Class<?> caller = getCallerClass(); checkAccess(caller, clazz, obj, modifiers); } } MethodAccessor ma = methodAccessor; // read volatile if (ma == null) { ma = acquireMethodAccessor(); } return ma.invoke(obj, args); }
invoke()方法中主要分爲兩部分:訪問控制檢查和調用MethodAccessor.invoke()實現方法執行。this
訪問控制檢測分有3步:spa
一、檢查override.net
二、快速檢查,判斷該方法的修飾符modifiers是否爲public3d
三、詳細檢查,經過方法的(protected/private/package)修飾符或方法的聲明類(例如子類能夠訪問父類的protected方法)與調用者caller之間的關係,判斷caller是否有權限訪問該方法。code
override屬性是Method的父類AccessibleObject中聲明的變量,使得程序能夠控制是否跳過訪問權限的檢查。另外,Method的實例對象中,override屬性的初始值設置爲false。
public void setAccessible(boolean flag) throws SecurityException { SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkPermission(ACCESS_PERMISSION); setAccessible0(this, flag); } /* Check that you aren't exposing java.lang.Class.<init>. */ private static void setAccessible0(AccessibleObject obj, boolean flag) throws SecurityException { if (obj instanceof Constructor && flag == true) { Constructor<?> c = (Constructor<?>)obj; if (c.getDeclaringClass() == Class.class) { throw new SecurityException("Can not make a java.lang.Class" + " constructor accessible"); } } obj.override = flag; }
部分代碼來源:https://blog.csdn.net/wenyuan65/article/details/81145900