之前的學習筆記,自用的反射筆記,比較雜亂無章,甚在內容全java
JAVA反射機制是在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意方法和屬性;這種動態獲取信息以及動態調用對象方法的功能稱爲java語言的反射機制。數組
基礎版:ide
public class reflection1 { public static void main(String[] args) throws Exception { Class.forName("xxx"); } } class xxx{ public xxx(){ System.out.println("xxx"); } static { System.out.println("xxx1"); } { System.out.println("xxx2"); } }
forName獲取一個類,當運行這段代碼,會動態調用static靜態代碼塊:函數
獲取函數方法:學習
public class reflection1 { public static void main(String[] args) throws Exception { Class clazz=Class.forName("xxx"); //實例化類,而後調用方法 clazz.getMethod("hello").invoke(clazz.newInstance()); } } class xxx{ public xxx(){ System.out.println("xxx"); } public void hello(){ System.out.println("hello"); } static { System.out.println("xxx1"); } { System.out.println("xxx2"); } }
執行函數invoke後,會調用類的構造方法,由於初始化優先級,{}會比構造方法先調用,而方法是最後調用測試
獲取構造方法:this
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class Reflection { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException { Class<?> clazz = Class.forName("zzz"); Constructor<?> constructor = clazz.getDeclaredConstructor(); constructor.setAccessible(true); constructor.newInstance(); } } class zzz{ private zzz(){ System.out.println("this is zzz"); } private zzz(String name){ System.out.println("this is "+name); } private zzz(int age,String name){ System.out.println("this is "+age+":"+name); } }
若是咱們想獲取有參構造方法怎麼作?spa
同樣使用getDeclaredConstructor();3d
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class Reflection { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException { Class<?> clazz = Class.forName("zzz"); Constructor<?> constructor = clazz.getDeclaredConstructor(String.class); constructor.setAccessible(true); constructor.newInstance("test"); } } class zzz{ private zzz(){ System.out.println("this is zzz"); } private zzz(String name){ System.out.println("this is "+name); } private zzz(int age,String name){ System.out.println("this is "+age+":"+name); } }
除了使用getDeclaredConstructor對象
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class Reflection { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException { Class<?> clazz = Class.forName("zzz"); // Constructor<?> constructor = clazz.getDeclaredConstructor(String.class); // constructor.setAccessible(true); // constructor.newInstance("test"); Constructor<?>[] constructors = clazz.getDeclaredConstructors(); Constructor constructor = constructors[0]; constructor.setAccessible(true); // 輸出內容 System.out.println(constructor); constructor.newInstance(); } } class zzz{ private zzz(){ System.out.println("this is zzz"); } private zzz(String name){ System.out.println("this is "+name); } private zzz(int age,String name){ System.out.println("this is "+age+":"+name); } }
若是想獲取有參構造方法:
有參構造方法在第1位置,那麼修改demo:
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class Reflection { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException { Class<?> clazz = Class.forName("zzz"); // Constructor<?> constructor = clazz.getDeclaredConstructor(String.class); // constructor.setAccessible(true); // constructor.newInstance("test"); Constructor<?>[] constructors = clazz.getDeclaredConstructors(); Constructor constructor = constructors[1]; constructor.setAccessible(true); // 輸出內容 System.out.println(constructor); constructor.newInstance("test"); } } class zzz{ private zzz(){ System.out.println("this is zzz"); } private zzz(String name){ System.out.println("this is "+name); } private zzz(int age,String name){ System.out.println("this is "+age+":"+name); } }
獲取私有構造方法,私有字段,私有方法:
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class reflection2 { public static <Feild> void main(String[] args) throws Exception { //獲取類 Class clazz=Class.forName("test"); //獲取私有方法 Constructor c = clazz.getDeclaredConstructor(); c.setAccessible(true); //獲取私有方法 Method method = clazz.getDeclaredMethod("test", String.class, String.class); method.setAccessible(true); method.invoke(c.newInstance(),"aaa","bbb"); //獲取私有字段 Field field = clazz.getDeclaredField("age"); field.setAccessible(true); System.out.println(field.get(c.newInstance())); } } class test{ private test(){ System.out.println("test"); } private int age=222; private void test(String name1,String name2){ System.out.println(name1+":"+name2); } }
即便構造方法,字段,方法是public,也是受用的。
public class reflection3 { public static void main(String[] args) throws Exception { //Class clazz=Class.forName("java.lang.Runtime"); // clazz.getMethod("exec", String.class).invoke(clazz.getMethod("getRuntime").invoke(clazz),"open /Users/maniac/aaaa.txt"); Class clazz = Class.forName("java.lang.Runtime"); //獲取構造方法,包含public,private,protect Constructor c = clazz.getDeclaredConstructor(); c.setAccessible(true); clazz.getMethod("exec", String.class).invoke(c.newInstance(),"open /Users/maniac/aaaa.txt"); } }
啓動成功:
java.lang.Runtime反射調用2:
因此直接調用:
public class reflection4 { public static void main(String[] args) throws Exception { // java.lang.Runtime.getRuntime().exec(); Class clazz=Class.forName("java.lang.Runtime"); clazz.getMethod("exec", String.class).invoke(clazz.getMethod("getRuntime").invoke(clazz),"open /Users/maniac/aaaa.txt"); } }
優先獲取最後的方法,而後往前移動。
流程:java.lang.Runtime.getRuntime().exec(command)->exec()->exec()->getRuntime()->java.lang.Runtime->command
修改私有屬性和方法裏面的屬性:
import jdk.nashorn.internal.objects.NativeDebug; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Reflection { private static java.lang.Object Object; public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException, NoSuchFieldException { Class<?> clazz = Class.forName("zzz"); Class.forName("java.lang.Runtime"); // Constructor<?> constructor = clazz.getDeclaredConstructor(String.class); // constructor.setAccessible(true); // constructor.newInstance("test"); Constructor<?>[] constructors = clazz.getDeclaredConstructors(); Constructor constructor = constructors[1]; constructor.setAccessible(true); // 輸出內容 System.out.println(constructor); // constructor.newInstance("test"); // Method xxx = clazz.getMethod("xxx"); // System.out.println(xxx); //實例化 Object o=constructor.newInstance("test"); Field field = clazz.getDeclaredField("name"); field.setAccessible(true); field.set(o,"hello"); Object xx=field.get(o); //修改變量 System.out.println(xx); // System.out.println(field.get(constructor.newInstance("test"))); // clazz.getMethod("xxx").invoke(constructor.newInstance("test")); // clazz.getDeclaredField("name").setAccessible(true); Method method = clazz.getDeclaredMethod("xxx"); method.setAccessible(true); //修改方法 method.invoke(o); } } class zzz{ private zzz(){ System.out.println("this is zzz"); } private zzz(String name){ System.out.println("this is "+name); } private zzz(int age,String name){ System.out.println("this is "+age+":"+name); } public int age=123; private String name="jack"; public void xxx(){ System.out.println(name); } }
總結:getMethod:是獲取方法
Field i = demo.getDeclaredField("i"); i.setAccessible(true); int modifiers = i.getModifiers();
返回類型有這些:
PUBLIC: 1 PRIVATE: 2 PROTECTED: 4 STATIC: 8 FINAL: 16 SYNCHRONIZED: 32 VOLATILE: 64 TRANSIENT: 128 NATIVE: 256 INTERFACE: 512 ABSTRACT: 1024 STRICT: 2048
去final修飾符修改字段:
測試demo:
Class<?> aClass = Class.forName("com.reflection.demo"); Field number = aClass.getDeclaredField("number"); number.setAccessible(true); Field modifiers = number.getClass().getDeclaredField("modifiers"); modifiers.setAccessible(true); modifiers.setInt(number,number.getModifiers()&~Modifier.FINAL); number.setInt(null,13); System.out.println(number.get(null));
反射調用內部類:
//反射調用內部類 @Test public void test4() throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException, NoSuchFieldException { Class c = Class.forName("com.test.BasicTest.refInnerClass"); Constructor declaredConstructor1 = c.getDeclaredConstructor(); declaredConstructor1.setAccessible(true); //經過方法名獲取方法 Method method = c.getDeclaredMethod("print"); //調用外部類方法 method.invoke(c.newInstance()); //內部類須要使用$分隔 Class c2 = Class.forName("com.test.BasicTest.refInnerClass$InnerClass"); Method method2 = c2.getDeclaredMethod("print2"); Constructor declaredConstructor = c2.getDeclaredConstructor(c); declaredConstructor.setAccessible(true); method2.setAccessible(true); //獲取方法 method2.invoke(declaredConstructor.newInstance(c.newInstance())); //修改isTrue爲true Field isTrue = c2.getDeclaredField("isTrue"); isTrue.setAccessible(true); Field modifiers = isTrue.getClass().getDeclaredField("modifiers"); modifiers.setAccessible(true); //去除final修飾符 modifiers.setInt(isTrue,isTrue.getModifiers()&~Modifier.FINAL); isTrue.setBoolean(null,true); System.out.println(isTrue.get(null)); //調用私有方法 Method test2 = c2.getDeclaredMethod("test2"); test2.setAccessible(true); test2.invoke(declaredConstructor.newInstance(declaredConstructor1.newInstance())); }
for循環反射調用內部類方法和字段:
//反射內部類批量調用方法,字段名字 @Test public void test5() throws ClassNotFoundException { com.test.BasicTest.refInnerClass refInnerClass = new refInnerClass(); Class<?> aClass = Class.forName("com.test.BasicTest.refInnerClass"); //獲取全部類 Class<?>[] declaredClasses = refInnerClass.class.getDeclaredClasses(); Arrays.stream(declaredClasses).forEach(clazz -> { Arrays.stream(clazz.getDeclaredMethods()).forEach(method -> { Arrays.stream(clazz.getDeclaredFields()).forEach(field -> { field.setAccessible(true); method.setAccessible(true); try { // 獲取內部類的構造方法,內部類的構造只能經過外部類來獲取 Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(aClass); declaredConstructor.setAccessible(true); // 由外部類對象來反射獲取內部類的對象 Object o = declaredConstructor.newInstance(aClass.newInstance()); method.invoke(o); Field modifiers = field.getClass().getDeclaredField("modifiers"); modifiers.setAccessible(true); modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); Object o1 = field.get(o); System.out.println(o1); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException | NoSuchFieldException e) { e.printStackTrace(); } }); }); }); }
for循環反射調用類的方法和字段:
@Test //反射批量調用方法,名字 public void test6() throws ClassNotFoundException { Class<?> aClass = Class.forName("com.test.BasicTest.reflectionDemo"); Arrays.stream(aClass.getDeclaredMethods()).forEach(method -> { Arrays.stream(aClass.getDeclaredFields()).forEach(field -> { method.setAccessible(true); field.setAccessible(true); try { Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();; declaredConstructor.setAccessible(true); method.invoke(declaredConstructor.newInstance()); Object o = field.get(null); System.out.println(o); } catch (IllegalAccessException | InvocationTargetException |NoSuchMethodException|InstantiationException e) { e.printStackTrace(); } }); }); }
可有可無的一些反射加載類縮寫:
一個數組 [Ljava.lang.String;
二維數組 [[Ljava.lang.String;
三維數組 [[[Ljava.lang.String;
float[].class=[F double[].class=[D long[].class=[J int[].class=[I short[].class=[S char[].class=[C byte[].class=[B Boolean[].class=[Ljava.lang.Boolean; Integer[].class=[Ljava.lang.Integer; Object[].class=[Ljava.lang.Object;
一個[爲一維數組,2個[爲2維,依次遞增
後續若是還有反射知識點再補充