java反射重要么_JAVA反射----这些知识你需要知道
前言:
在學習JAVA的反射之前我覺得很有必要花幾分鐘時間了解一下JVM的內存結構。如果一開始就說什么是反射,以及反射的API。這樣做是很難真正的理解反射的。
JVM是JAVA跨平臺的核心,其結構為上圖所示。我們注意到其運行時數據區也就是我們常說的內存結構包括堆區,方法區,棧區等。那么我們JAVA程序在運行的時候,運行時數據區每個區域存儲的哪些數據呢。
程序計數器:簡單將程序計數器就是用來指示需要執行哪條指令。由此看出它是線程私有的,因為我們知道多線程的本質是線程搶占CPU時間片的過程,所以我們線程中指令不斷的終止和運行,所以要回到運行狀態必須要程序計數器記錄下應該執行的指令編號。(因為每天指令的大小是固定的所以不會存在內存泄漏的情況)
JAVA棧:JAVA棧也稱為JAVA執行方法的內存模型,存儲了方法中聲明的局部變量包括聲明的局部變量形參,運行時常量池引用以及返回地址。JAVA的運行其實就是一個方法棧幀的壓棧與彈棧的過程。
堆區:Java中的堆是用來存儲對象本身的以及數組(當然,數組引用是存放在Java棧中的)。只不過和C語言中的不同,在Java中,程序員基本不用去關心空間釋放的問題,Java的垃圾回收機制會自動進行處理。因此這部分空間也是Java垃圾收集器管理的主要區域。另外,堆是被所有線程共享的,在JVM中只有一個堆。
方法區:方法區在JVM中也是一個非常重要的區域,它與堆一樣,是被線程共享的區域。在方法區中,存儲了每個類的信息(包括類的名稱、方法信息、字段信息)、靜態變量、常量以及編譯器編譯后的代碼等。在Class文件中除了類的字段、方法、接口等描述信息外,還有一項信息是常量池,用來存儲編譯期間生成的字面量和符號引用。在方法區中有一個非常重要的部分就是運行時常量池,它是每一個類或接口的常量池的運行時表示形式,在類和接口被加載到JVM后,對應的運行時常量池就被創建出來。當然并非Class文件常量池中的內容才能進入運行時常量池,在運行期間也可將新的常量放入運行時常量池中,比如String的intern方法。
類加載的過程其實就是JVM將外部的靜態class字節碼加載到JVM方法區形成動態數據并在堆中形成一個java.lang.Class對象。這個對象相當于一面鏡子與方法區中真正對象對應,這個Class對象就是反射的核心。
了解Class
既然Class對象是反射的核心,那么什么是Class呢?我們來看一下JDK7中是怎么定義的:
* Instances of the class{@code Class} represent classes and* interfaces in a running Java application. An enumis a kind of* class and an annotation is a kind of interface. Every array also* belongs to a classthat is reflected as a {@code Class} object*that is shared by all arrays with the same element type and number* of dimensions. The primitive Java types ({@code boolean},* {@code byte}, {@code char}, {@code short},* {@code int}, {@code long}, {@code float}, and* {@code double}), and the keyword {@code void} are also*represented as {@code Class} objects.*
*
{@code Class} has no publicconstructor. Instead {@code Class}*objects are constructed automatically by the Java Virtual Machine as classes* are loaded and by calls to the {@code defineClass} method in the class
* loader.
大概意思為:Class的實例代表正在運行JAVA程序中的對象和接口。枚舉類型是一種對象而注解是一種接口。每個數組是被映射為Class的一個類,而具有相同數據類型和維數的數組都共享該Class類。基本數據類型依然是Class對象。Class沒有公共的構造方法。所有的Class對象都是在JVM被加載的時候自動調用defineClass創建。
反射作用
可以通過反射得到類成員變量,成員方法以及構造方法并可以操作他們,即使是私有的也可以訪問并操作。
提高代碼靈活性
反射示例
首先創建一個測試Student類:
public classStudent {private intage;privateString name;private double score; //三個私有屬性
public intgetAge() {returnage;
}public void setAge(intage) {this.age =age;
}publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}public doublegetScore() {returnscore;
}public void setScore(doublescore) {this.score =score;
}public Student(){//公共不帶參構造
}private Student(int age,String name,double score){//私有帶參構造
this.age =age;this.name =name;this.score =score;
}
}
三種方式獲取Class對象:
Class clazz1 = Class.forName("reflection.Student");
Class clazz2= Student.class;
Student student= newStudent();
Class clazz3=student.getClass();
System.out.println(clazz1==clazz2);
System.out.println(clazz1==clazz3);
輸出結果為:ture/ture 根據傳遞性可知這三個對象是同一個
2.通過反射得到實例對象
Class clazz1 = Class.forName("reflection.Student");
Object obj= clazz1.newInstance();//調用了無參構造函數
3.通過反射得到類私有變量并賦值
Class clazz1 = Class.forName("reflection.Student");
Object o=clazz1.newInstance();
Field files1= clazz1.getDeclaredField("age");
files1.setAccessible(true); //打破私有訪問屬性
files1.set(o, 12);
System.out.println(files1.get(o));
4.通過反射執行私有構造函數
Constructor a = clazz1.getDeclaredConstructor(int.class,String.class,double.class);
a.setAccessible(true);
Student stu= (Student)a.newInstance(12,"李強",12);
System.out.println("學生信息獲取到:"+stu.getName());
5.通過反射執行成員方法
Constructor a = clazz1.getDeclaredConstructor(int.class,String.class,double.class);
a.setAccessible(true);
Student stu= (Student)a.newInstance(12,"李強",12);
System.out.println("學生信息獲取到:"+stu.getName());
Method method= clazz1.getMethod("setName", String.class);
method.invoke(stu,"芳芳");
System.out.println("學生信息獲取到:"+stu.getName());
總結
以上是生活随笔為你收集整理的java反射重要么_JAVA反射----这些知识你需要知道的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java技术入门培训_入门java怎么自
- 下一篇: java newdirectorystr