第16篇-JAVA 類加載與反射

2022-03-11 11:29 更新
  • 每篇一句 :敢于彎曲,是為了更堅(jiān)定的站立
  • 初學(xué)心得: 追求遠(yuǎn)中的歡聲笑語,追求遠(yuǎn)中的結(jié)伴同行
  • (筆者:JEEP/711)[JAVA筆記 | 時(shí)間:2017-05-12| JAVA 類加載與反射 ]

1.類加載

  • 類加載器負(fù)責(zé)將 .class 文件(可能在磁盤上, 也可能在網(wǎng)絡(luò)上) 加載到內(nèi)存中, 并為之生成對應(yīng)的 java.lang.Class 對象
    - 當(dāng)程序主動(dòng)使用某個(gè)類時(shí),如果該類還未被加載到內(nèi)存中,系統(tǒng)會(huì)通過加載、連接、初始化三個(gè)步驟來對該類進(jìn)行初始化,如果沒有意外,JVM將會(huì)連續(xù)完成這三個(gè)步驟,所以有時(shí)也把這三個(gè)步驟統(tǒng)稱為類加載或類初始化。
    - 類加載指的是將類的class文件讀入內(nèi)存,并為之創(chuàng)建一個(gè)java.lang.Class對象,也就是說當(dāng)程序使用任何類時(shí),系統(tǒng)都會(huì)為之建立一個(gè)java.lang.Class對象

2.類數(shù)據(jù)的來源

通過使用不同的類加載器,可以從不同來源加載類的二進(jìn)制數(shù)據(jù),通常有如下幾種來源:
- 從本地文件系統(tǒng)來加載class文件,這是前面絕大部分示例程序的類加載方式。
- 從JAR包中加載class文件,這種方式也是很常見的,前面介紹JDBC編程時(shí)用到的數(shù)據(jù)庫驅(qū)動(dòng)類就是放在JAR文件中,JVM可以從JAR文件中直接加載該class文件
- 通過網(wǎng)絡(luò)在加載class文件
- 把一個(gè)Java源文件動(dòng)態(tài)編譯、并執(zhí)行加載

3.類的連接

當(dāng)類被加載之后,系統(tǒng)為之生成一個(gè)對應(yīng)的Class對象,接著將會(huì)進(jìn)入連接階段,連接階段將會(huì)負(fù)責(zé)把類的二進(jìn)制數(shù)據(jù)合并到JRE中

類連接又可分為如下三個(gè)階段:
- 驗(yàn)證:驗(yàn)證階段用于檢驗(yàn)被加載的類是否有正確的內(nèi)部結(jié)構(gòu),并和其他類協(xié)調(diào)一致
- 準(zhǔn)備:類準(zhǔn)備階段則負(fù)責(zé)為類的靜態(tài)屬性分配內(nèi)存,并設(shè)置默認(rèn)初始值
- 解析:將類的二進(jìn)制數(shù)據(jù)中的符號(hào)引用替換成直接引用

4.類加載器

類加載器負(fù)責(zé)將.class文件(可能在磁盤上,也可能在網(wǎng)絡(luò)上)加載到內(nèi)存中,并為之生成對應(yīng)的java.lang.Class對象

當(dāng)JVM啟動(dòng)時(shí),會(huì)形成由三個(gè)類加載器組成的初始類加載器層次結(jié)構(gòu):
- Bootstrap ClassLoader:根類加載器。
- Extension ClassLoader:擴(kuò)展類加載器。
- System ClassLoader:系統(tǒng)類加載器

5.什么是反射

反射就是把Java類中的各種成分映射成一個(gè)個(gè)的java對象。例如,一個(gè)類有:成員變量,方法,構(gòu)造方法,包等等信息,利用反射技術(shù)可以對一個(gè)類進(jìn)行解剖,把各個(gè)組成部分映射成一個(gè)個(gè)對象

6.Class類

Class類用于表示.class文件
如何得到某個(gè)class文件對應(yīng)的class對象

類名.class,
對象.getClass()
Class.forName(“類名”)

數(shù)組類型的Class實(shí)例對象

Class.isArray()

7.Constructor類

Constructor類的實(shí)例對象代表類的一個(gè)構(gòu)造方法
得到某個(gè)類所有的構(gòu)造方法,例:

Constructor [] constructors= Class.forName("java.lang.String").getConstructors();

得到某一個(gè)構(gòu)造方法,例:


Constructor constructor = Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);

利用構(gòu)造方法創(chuàng)建實(shí)例對象:

String str = (String)constructor.newInstance(“abc”);

Class類的newInstance()方法也可創(chuàng)建類的實(shí)例,其內(nèi)部工作原理是先得無參的構(gòu)造方法,再用構(gòu)造方法創(chuàng)建實(shí)例對象

String obj =(String)Class.forName("java.lang.String").newInstance();

8.內(nèi)省(Introspector)

訪問JavaBean屬性的兩種方式
- 直接調(diào)用bean的setXXX或getXXX方法
- 通過內(nèi)省技術(shù)訪問(java.beans包提供了內(nèi)省的API),內(nèi)省技術(shù)訪問也提供了兩種方式
- 通過PropertyDescriptor類操作Bean的屬性
- 通過Introspector類獲得Bean對象的 BeanInfo,然后通過 BeanInfo 來獲取屬性的描述器( PropertyDescriptor ),通過這個(gè)屬性描述器就可以獲取某個(gè)屬性對應(yīng)的 getter/setter 方法,然后通過反射機(jī)制來調(diào)用這些方法

內(nèi)省—beanutils工具包
Apache組織開發(fā)了一套用于操作JavaBean的API,這套API考慮到了很多實(shí)際開發(fā)中的應(yīng)用場景,因此在實(shí)際開發(fā)中很多程序員使用這套API操作JavaBean,以簡化程序代碼的編寫

Beanutils工具包的常用類:
- BeanUtils
- PropertyUtils
- ConvertUtils.regsiter(Converter convert, Class clazz)
- 自定義轉(zhuǎn)換器

9.反射案例


<br> package com.mvc.bean;
<br> import com.mvc.service.imp.UserServiceImp;
<br> import java.util.ResourceBundle;
<br> /**
<br>  * Created by JEEP-711 
<br>  */
<br> public class BeanFactory {
<br>     private static ResourceBundle bundle;
<br>     static {
<br>         bundle = ResourceBundle.getBundle("instance"); //文件內(nèi)容
<br>     }
<br>     public static <T& T getInstance(String key, Class<T& clazz){
<br>         try {
<br>             String className = bundle.getString(key);//類的全路徑
<br>             return (T)Class.forName(className).newInstance();//反射方式
<br>         } catch (Exception e) {
<br>             throw new RuntimeException(e);
<br>         }
<br>     }
<br> }
<br> ```
<br> ```
<br> package com.mvc.controller;
<br> import com.alibaba.fastjson.JSON;
<br> import com.mvc.bean.BeanFactory;
<br> import com.mvc.bean.Type;
<br> import com.mvc.service.ITypeService;
<br> import com.mvc.service.imp.TypeServiceImpl;
<br> import org.apache.commons.beanutils.BeanUtils;
<br> import javax.servlet.ServletException;
<br> import javax.servlet.http.HttpServlet;
<br> import javax.servlet.http.HttpServletRequest;
<br> import javax.servlet.http.HttpServletResponse;
<br> import java.io.IOException;
<br> import java.io.Writer;
<br> import java.util.List;
<br> /**
<br>  * Created by JEEP-711 
<br>  */
<br> public class TypeServlet extends HttpServlet{
<br>                                                //反射
<br> ITypeService iTypeService = BeanFactory.getInstance("typeService",ITypeService.class);
<br>     @Override
<br>     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
<br>         resp.setContentType("text/html;charset=UTF-8");//設(shè)置UTF-8編碼格式
<br>         req.setCharacterEncoding("UTF-8");//設(shè)置UTF-8編碼格式
<br>         String method = req.getParameter("m");
<br>         if("add".equals(method)){
<br>             add(req,resp);//調(diào)用add方法
<br>         }else if("update".equals(method)){
<br>             update(req,resp);//調(diào)用修改方法
<br>         }else if("ajax_all".equals(method)){
<br>             ajaxAll(req,resp);
<br>         }else if("delete".equals(method)){
<br>             delete(req,resp);
<br>         }else {
<br>             index(req,resp);//調(diào)用錯(cuò)誤方法
<br>         }
<br>     }
<br> }
<br> ```

初學(xué)(JAVA 類加載與反射 高級階段) 難點(diǎn): ★★★★★

希望每一篇文章都能夠?qū)ψx者們提供幫助與提升,這乃是每一位筆者的初衷

感謝您的閱讀 歡迎您的留言與建議

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)