反射機制雖然說增加了代碼的複雜程度但是提高代碼的靈活性,在以後的框架的學習中,配置文件的修改大部分都是利用的反射機制。和利用反射機制去做Runtime類這下麵方法exec,進行命令執行,後面去學習一下 ...
0x00前言和思維導圖
1.反射機制定義:java反射機制是指在java代碼執行過程中,對於任意一個類,可以獲取這個類的屬性與方法;對於任意一個對象,可以獲取、修改這個對象的屬性值,調用對象的方法。這種動態獲取信息和調用方法的技術就是java中的反射機制。
2.首先需要瞭解Class類(全限定名稱是java.lang.Class)和class對象。class對象就是由Class類創建的對象,只是這個創建過程不是由用戶主動創建的,而是由JVM自動實現的。JVM會為項目中每一個類(不論是JDK自帶的類、第三方jar包的類、還是自己編寫的類)創建一個class對象,用來保存與這個類相關的信息。class對象只與類有關,與對象無關。
0x01獲取位元組碼文件
方法一:Class.forName(" "),中間需要一個String類型的classname;
Class c3=Class.forName("java.util.Date");
(它的執行胡導致類的載入會導致靜態模塊的代碼執行)
方法二:每個對象都有一個繼承與Object的方法叫做getClass;返回的是一個Class
public final native Class<?> getClass();
方法三:java每一種數據類型都用有一個屬性叫做class屬性
Class Z=String.class;
class My_Reflect_one{
public static void main(String[] args) {
Class c1=null;
try {
c1 = Class.forName("java.lang.String");
Class c3=Class.forName("java.util.Date");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String s="abc";
Class X=s.getClass();
System.out.println(c1==X);//返回值是True,位元組碼文件裝載到JVM的時候只會裝載一份
Class Z=String.class;
Class y=Integer.class;
}
}}
0x02獲取Field(獲取屬性)
1.先定義一個類
class ReflectTest{
public int no=0;
private String name;
protected int age;
boolean flag;
}
2.getFields()
獲取所有是public修飾的屬性
public static void main(String[] args) throws Exception{
Class Test_Class=Class.forName("zhonglin.www.ReflectTest");
Field[] fields= Test_Class.getFields();}
3.getDeclaredFields()
獲取所有屬性暴力破解,不管修飾符
public static void main(String[] args) throws Exception{
Class Test_Class=Class.forName("zhonglin.www.ReflectTest");
Field[] fs= Test_Class.getDeclaredFields();//暴力獲取所有屬性
System.out.println(fs.length);//4個長度}
4.getTyp()
獲取數據類型
(1)看下構造函數,返回值是一個Class
public Class<?> getType() {
return type;
}
public static void main(String[] args) throws Exception{
Class Test_Class=Class.forName("zhonglin.www.ReflectTest");
Field[] fs= Test_Class.getDeclaredFields();//暴力獲取所有屬性
System.out.println(fs.length);//4個長度
for (Field field :fs){
Class filedtype=field.getType();//接受返回的Class
String fName=filedtype.getName();//調用getname方法
System.out.println(fName);
System.out.println(field.getName());
}}
5、getModifiers()和Modifier.toString()
去找到屬性的修飾符
(1)構造函數 public int getModifiers()
它的返回值是一個intpublic static String toString(int mod)
它可以把對應的int輸出成對應的修飾符
public static void main(String[] args) throws Exception{
Class Test_Class=Class.forName("zhonglin.www.ReflectTest");
Field[] fs= Test_Class.getDeclaredFields();//暴力獲取所有屬性
System.out.println(fs.length);//4個長度
for (Field field:fs){
int i=field.getModifiers();
String modifiter =Modifier.toString(i);
System.out.println(modifiter);
}}
6.通過get和set方法訪問和修改屬性
(1)通過newInstance()方法構造出一個對象
(2)通過getDeclaredField(name)獲取一個屬性的值賦值給一個Field對象,可以同Filed對象.get/set
(3)get和set的構造方法
a.set():public void set(Object obj, Object value)
b.get(): public Object get(Object obj)
class Reflect_four{
public static void main(String[] args) throws Exception {
Class Test_class=Class.forName("zhonglin.www.ReflectTest");
//操作對象屬性
Object obj= Test_class.newInstance();
Field nofiled=Test_class.getDeclaredField("no");
nofiled.set(obj,2222);
System.out.println(nofiled.get(obj));
//訪問私有屬性
Field namefield=Test_class.getDeclaredField("name");
namefield.setAccessible(true);//打破封裝
namefield.set(obj,"jsckson");
System.out.println(namefield.get(obj));
}
}
7.反編譯文件(拓展)
綜合使用學習到的方法
class Myreflect_Three{//構造好框架
public static void main(String[] args) throws Exception {
StringBuilder stringBuilder=new StringBuilder();
Class Test_class=Class.forName("zhonglin.www.ReflectTest");
stringBuilder.append(Modifier.toString(Test_class.getModifiers())+"class "+Test_class.getSimpleName()+"{");
Field[] fields=Test_class.getDeclaredFields();
stringBuilder.append("\n");
for (Field field:fields)
{
stringBuilder.append("\t");
stringBuilder.append(Modifier.toString(field.getModifiers()));//獲取屬性的修飾符
stringBuilder.append(" ");
stringBuilder.append(field.getType().getSimpleName());//獲取屬性類型
stringBuilder.append(" ");
stringBuilder.append(field.getName());//獲取屬性的名字
stringBuilder.append(";\n");
}
stringBuilder.append("}");
System.out.println(stringBuilder);
}
}
0x02反射Method
1.基礎方法和反射屬性差不多。
2.方法的使用
***getDeclaredMethod("方法名",...args(參數))獲取方法
getReturnType()獲取返回值類型
Modifier.toString((method1.getModifiers())獲取修飾符
public Object invoke(Object obj, Object... args)調用方法***
3.看一下完整代碼
class Reflect_five{
public static void main(String[] args) throws Exception {
Class Test_class=Class.forName("zhonglin.www.ReflectTest2");
Method[] method = Test_class.getDeclaredMethods();//獲取全部方法
for (Method method1:method){
System.out.println(method1.getName());
//獲取返回值類型1
System.out.println(method1.getReturnType());
//獲取方法的修飾符
System.out.println(Modifier.toString((method1.getModifiers())));
//獲取參數列表
Class[] classes=method1.getParameterTypes();
for (Class parmeterType:classes){
System.out.println(parmeterType.getSimpleName());
}
}
}
}
class Reflect_six{
public static void main(String[] args) throws Exception{
Class Test_class=Class.forName("zhonglin.www.ReflectTest2");
Object obj=Test_class.newInstance();
Method LONIN=Test_class.getDeclaredMethod("longin", String.class, String.class);
Object result=LONIN.invoke(obj,"root","root");
}
}
0x03反射Constructor
1.基礎方法一致:
getModifiers()隨後用toString輸出;//獲取修飾符
getSimpleName()//獲取構造方法名其實就是獲取類名
getParameterTypes()//獲取參數列表
public T newInstance();//創建一個對象,這個對象可以用一個Object去獲取,創建成功及調用了構造函數
點擊查看代碼
class Refldct_seven{
public static void main(String[] args) throws Exception{
StringBuilder stringBuilder=new StringBuilder();
Class class_Test=Class.forName("zhonglin.www.ReflectTest3");
stringBuilder.append(class_Test.getSimpleName());
stringBuilder.append("{");
stringBuilder.append("}");
System.out.println(stringBuilder);
Constructor[] constructors=class_Test.getDeclaredConstructors();
for (Constructor constructor:constructors){
System.out.println(constructor.getDeclaringClass().getSimpleName());
constructor.getModifiers();
constructor.getParameterTypes();
}
//創建對象
Object obj= class_Test.newInstance();
System.out.println(obj);
//有參構造方法怎麼調用
Constructor constructor2=class_Test.getDeclaredConstructor(int.class,String.class,String.class);
Object obj2= constructor2.newInstance(2,"hellow","hellow");
}
}
1.學到這裡發現其實都是一些方法的使用
getSuperclass(): public native Class getSuperclass();//獲取父類
getInterfaces():public Class[] getInterfaces();//獲取全部介面返回值是一個路徑可用迴圈獲得
//看下實例;
class Refldct_eight{
public static void main(String[] args) throws Exception{
Class class_Test=Class.forName("zhonglin.www.ReflectTest4");
class_Test.getSuperclass().getSimpleName();
Class[] in= class_Test.getInterfaces();
for (Class IN: in) {
System.out.println(IN.getSimpleName());
}
}
}
0x05
反射機制雖然說增加了代碼的複雜程度但是提高代碼的靈活性,在以後的框架的學習中,配置文件的修改大部分都是利用的反射機制。和利用反射機制去做Runtime類這下麵方法exec,進行命令執行,後面去學習一下