第16篇-JAVA 類加載與反射

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

1.類加載

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

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

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

3.類的連接

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

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

4.類加載器

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

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

5.什么是反射

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

6.Class類

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

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

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

Class.isArray()

7.Constructor類

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

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

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


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

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

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

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

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 ),通過這個屬性描述器就可以獲取某個屬性對應(yīng)的 getter/setter 方法,然后通過反射機制來調(diào)用這些方法

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

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

9.反射案例

  1. <br> package com.mvc.bean;
  2. <br> import com.mvc.service.imp.UserServiceImp;
  3. <br> import java.util.ResourceBundle;
  4. <br> /**
  5. <br> * Created by JEEP-711
  6. <br> */
  7. <br> public class BeanFactory {
  8. <br> private static ResourceBundle bundle;
  9. <br> static {
  10. <br> bundle = ResourceBundle.getBundle("instance"); //文件內(nèi)容
  11. <br> }
  12. <br> public static <T& T getInstance(String key, Class<T& clazz){
  13. <br> try {
  14. <br> String className = bundle.getString(key);//類的全路徑
  15. <br> return (T)Class.forName(className).newInstance();//反射方式
  16. <br> } catch (Exception e) {
  17. <br> throw new RuntimeException(e);
  18. <br> }
  19. <br> }
  20. <br> }
  21. <br> ```
  22. <br> ```
  23. <br> package com.mvc.controller;
  24. <br> import com.alibaba.fastjson.JSON;
  25. <br> import com.mvc.bean.BeanFactory;
  26. <br> import com.mvc.bean.Type;
  27. <br> import com.mvc.service.ITypeService;
  28. <br> import com.mvc.service.imp.TypeServiceImpl;
  29. <br> import org.apache.commons.beanutils.BeanUtils;
  30. <br> import javax.servlet.ServletException;
  31. <br> import javax.servlet.http.HttpServlet;
  32. <br> import javax.servlet.http.HttpServletRequest;
  33. <br> import javax.servlet.http.HttpServletResponse;
  34. <br> import java.io.IOException;
  35. <br> import java.io.Writer;
  36. <br> import java.util.List;
  37. <br> /**
  38. <br> * Created by JEEP-711
  39. <br> */
  40. <br> public class TypeServlet extends HttpServlet{
  41. <br> //反射
  42. <br> ITypeService iTypeService = BeanFactory.getInstance("typeService",ITypeService.class);
  43. <br> @Override
  44. <br> protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  45. <br> resp.setContentType("text/html;charset=UTF-8");//設(shè)置UTF-8編碼格式
  46. <br> req.setCharacterEncoding("UTF-8");//設(shè)置UTF-8編碼格式
  47. <br> String method = req.getParameter("m");
  48. <br> if("add".equals(method)){
  49. <br> add(req,resp);//調(diào)用add方法
  50. <br> }else if("update".equals(method)){
  51. <br> update(req,resp);//調(diào)用修改方法
  52. <br> }else if("ajax_all".equals(method)){
  53. <br> ajaxAll(req,resp);
  54. <br> }else if("delete".equals(method)){
  55. <br> delete(req,resp);
  56. <br> }else {
  57. <br> index(req,resp);//調(diào)用錯誤方法
  58. <br> }
  59. <br> }
  60. <br> }
  61. <br> ```

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

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

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

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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號