java 反射 内存_Java内存到反射入门
Java內(nèi)存到反射入門(一)
初識(shí)Java內(nèi)存
平常我們最常提到的的JAVA分區(qū)是這三個(gè)分區(qū)
其中方法區(qū)是一個(gè)特殊的堆,功能如圖上所示。
初識(shí)反射:框架設(shè)計(jì)的靈魂
反射的功能:將類的各個(gè)組成部分封裝為對(duì)象,并在程序運(yùn)行的過(guò)程中可以調(diào)用它們。
Java代碼的三個(gè)階段
我們平時(shí)書寫的java代碼,從書寫完成到內(nèi)存中執(zhí)行主要經(jīng)歷了三個(gè)階段:Source 源代碼階段,class類對(duì)象階段,Runtime運(yùn)行時(shí)階段。下圖以一個(gè)簡(jiǎn)單的Person類來(lái)舉例說(shuō)明。
第一階段:Source源代碼階段
首先,我們編寫好了一個(gè)Person類的代碼,它由成員變量,構(gòu)造方法,成員方法三部分組成。
public class Person{
private String name;
private int age;
public Person(){}
public void eat(){}
}
此時(shí)它是一個(gè)Person.java文件。還不能運(yùn)行,接著我們要用javac命令編譯它,使生成一個(gè)Person.Class字節(jié)碼文件。
這個(gè)文件我們并不能看懂,其實(shí)里面主要包含三部分內(nèi)容:成員變量,成員方法和構(gòu)造方法,還有一些諸如包名的信息。
至此,源代碼和字節(jié)碼都是以文件的形式儲(chǔ)存在硬盤上的,還未進(jìn)入內(nèi)存,此階段我們稱之為Source源代碼階段。
第二階段:Class類對(duì)象階段
要想由第一個(gè)階段進(jìn)入第二個(gè)階段,要經(jīng)過(guò)一個(gè)加載的過(guò)程。由類加載器ClassLoder將class文件加載到內(nèi)存中,并生成該類的class類對(duì)象。class類對(duì)象是來(lái)描述字節(jié)碼文件的,字節(jié)碼文件被封裝為三大部分:
1.成員變量被封裝為Field對(duì)象,并用Filed[]存儲(chǔ)。
2.構(gòu)造方法被封裝為Constructor對(duì)象,并用Constructor[]存儲(chǔ)。
3.成員方法被封裝為Method對(duì)象,并用Method[]存儲(chǔ)。
這樣的封裝就是反射機(jī)制,經(jīng)過(guò)了這樣的封裝后,我們就可以在程序運(yùn)行的過(guò)程中來(lái)操作這些對(duì)象了。即獲取,修改變量和執(zhí)行方法等。
舉個(gè)栗子:在IDEA等IDE中,寫如下一段代碼:
//定義了一個(gè)字符串變量,并嘗試調(diào)用它自帶的方法
String str = "abc";
str.
在按下str后面這個(gè).后,IDEA會(huì)提示許多的方法。
那么為什么IDEA會(huì)提示這些方法呢?其實(shí)內(nèi)部就是反射機(jī)制。 定義了一個(gè)String變量后,則字符串的字節(jié)碼文件就會(huì)被加載進(jìn)內(nèi)存。在內(nèi)存中就有了String的class類對(duì)象,里面封裝了Method[]存儲(chǔ)了所有String的方法。所以只要挨個(gè)顯示一下就可以了。
第三階段:Runtime運(yùn)行時(shí)階段
第二階段通過(guò)創(chuàng)建對(duì)象等操作就會(huì)進(jìn)入第三階段,創(chuàng)建對(duì)象時(shí)就會(huì)根據(jù)這個(gè)class類對(duì)象創(chuàng)建一個(gè)真正的Person對(duì)象。
獲得class類的三種方法
Class.forName("全類名"):將字節(jié)碼文件加載進(jìn)內(nèi)存,返回Class對(duì)象 * 多用于配置文件,將類名定義在配置文件中。讀取文件,加載類
//如獲取Person類的.Class文件
Class a = Class.forName("Domain.Person");//Domian是Person類所在包
類名.class:通過(guò)類名的屬性class獲取,該方法多用于參數(shù)的傳遞。
Class a = Person.calss;
對(duì)象.getClass():getClass()方法在Object類中定義著,該方法多用于對(duì)象的獲取字節(jié)碼的方式
Person person = new Person();
Class a = person.getClass();
Tip:同一個(gè)字節(jié)碼文件(*.class)在一次程序運(yùn)行過(guò)程中,只會(huì)被加載一次,不論通過(guò)哪一種方式獲取的Class對(duì)象都是同一個(gè)。
//采用多種方式得到.Class文件
Class a = Class.forName("Domain.Person");
Person person1 = new Person();
Person person2 = new Person();
Class b = person1.getClass();
Class c = Person.class;
Class d = person2.getClass();
//不管以哪種方式得到的.Class類,只要是Person類的,那就是一樣的。
System.out.println(a==b); //true
System.out.println(c==b); //true
System.out.println(a==c); //true
System.out.println(a==d); //true
Class類的用法
在熟悉了Class類的獲取方法后,自然要熟悉其用法。
//以下是測(cè)試用的Person類
public class Person {
private String name;
private int age;
private int id;
public Person() {
}
public Person(String name, int age, int id) {
this.name = name;
this.age = age;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "Person{" +
"name='" \+ name \+ '\\'' +
", age=" \+ age +
", id=" \+ id +
'}';
}
}
用法一:獲取類的名字
方法有兩個(gè):
String getName(); //返回類的包名+類名
String getSimpleName();//獲取簡(jiǎn)單類名
Class c1 = Person.class;
System.out.println(c1.getName()); //該方法獲取類的全名,輸出Domain.Person
System.out.println(c1.getSimpleName());//該方法獲取類的簡(jiǎn)單名,即Person
用法二:獲得類的屬性
方法有四個(gè):
Field[] getFields() :獲取所有public修飾的成員變量
Field getField(String name) 獲取指定名稱的 public修飾的成員變量
Field[] getDeclaredFields() 獲取所有的成員變量,不考慮修飾符
Field getDeclaredField(String name)
用法三:獲得類的方法
方法有四個(gè):
Method[] getMethods() ;
Method getMethod(String name, 類>... parameterTypes) ;
Method[] getDeclaredMethods() ;
Method getDeclaredMethod(String name, 類>... parameterTypes) ;
注意第一個(gè)方法會(huì)獲取包括本類和父類的所有public方法。 第二個(gè)方法只會(huì)獲取本類的所有方法,包括private的,不包括父類的方法。
獲取指定方法的第一個(gè)參數(shù)是方法的名稱,第二個(gè)參數(shù)是要獲取的方法的參數(shù)類型,如setName(String name);函數(shù),參數(shù)是String,則此處寫String.Class;
用法四:獲得構(gòu)造器(構(gòu)造方法)
有四種方法:
獲取構(gòu)造方法們
Constructor>[] getConstructors()
Constructor getConstructor(類>... parameterTypes)
Constructor getDeclaredConstructor(類>... parameterTypes)
Constructor>[] getDeclaredConstructors() ;
總結(jié)
以上是生活随笔為你收集整理的java 反射 内存_Java内存到反射入门的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Linux多线程——使用互斥量同步线程
- 下一篇: bandizip修改压缩文件内容_Ban