天天看點

初學JavaSE筆記——(十八)反射

一、類加載

        應用程式的啟動:java  類名——>調用JVM,啟動JVM程序,啟動mian主線程,加載主類。

        應用程式的結束:1、所有代碼執行完畢;2、存在沒有處理的Exception、Error;3、System.exit(0);4、運作平台強制結束。

        1、類的生命周期

            (1)加載:把類的位元組碼檔案加載到JVM的記憶體方法區中并且生成一個Class類型的對象。  

                ClassLoader(類加載器)加載(通過流的技術,也可自定義類記載器), 生成Class類型對象,通過Class類的方法操作類的屬性、方法、構造器。           

            (2)連接配接:a、驗證-位元組碼檔案格式是否正确;b、準備-為類變量(靜态變量)配置設定空間,預設初始化;c、解析-把符号引用替換成直接引用(指針:指向記憶體位址)。

            (3)初始化:當類被主動使用時,為類變量進行聲明處和靜态塊處初始化。

                    1、當虛拟機Java指令運作啟動類;

                    2、當建立某個類的新執行個體時;

                    3、當調用某個類的靜态成員;

                    4、當初始化某個子類時,該子類的所有父類都會被初始化;

                    5、當使用反射方法強制建立某個類或接口的對象時;   Demo.class.newInstance();   

                    static final類型不能導緻初始化;

            (4)使用

            (5)解除安裝

        2、類加載器

            根類加載器<——擴充類加載器<——系統類加載器<——自定義類加載器

            根類加載器:加載核心類庫,d:\java\jdk1.8.0_144\jre\lib,c++寫的,顯示為null。

            擴充類加載器:加載擴充類庫,lib\ext。

            系統類加載器:應用類加載器,classpath路徑下的類。

            自定義類加載器:不是classpath路徑,自己指定路徑。

初學JavaSE筆記——(十八)反射

            父類委托機制(雙親):

            調用ClassLoader後,通過Class<?> c=findLoadedClass(name)查找此類是否被加載,已加載傳回Class對象,未加載傳回null;未加載,系統類加載器先不加載,檢視父類加載器(擴充類加載器)是否存在,父類遞歸調用父類(根類加載器)加載,如根類加載器不存在,擴充類加載器加載,擴充類加載器不存在,系統類加載器加載。

                1、獲得系統類加載器:ClassLoader.getSystemClassLoader().loadClass("包名.類名");

                2、加載并初始化:Class.forName("包名.類名",true,ClassLoader.getSystemClassLoader());true表示進行初始化,後面是指定加載器。

                                             Class.forName("包名.類名");

            自定義加載器:

            自定義類,屬性為類的路徑——>繼承ClassLoader,重寫findClass方法(用流把.class檔案讀出來、解析成方法區資料結構);

初學JavaSE筆記——(十八)反射

        ClassLoader類的defineClass(name,b[ ],0,len)将一個byte數組轉換為Class類的執行個體;

        Class類的forName(name類的完全限定名,true初始化類,loader加載器)傳回類關聯的Class對象;

        FileInputStream類的read(byte[ ] b)從輸入流中讀入數組,傳回讀入的位元組總數;

二、反射                

        反射是從方法區的位元組碼中動态的獲得類中的資訊。 

        獲得 類名. class 對應的Class對象:

        a、Class<?> c=Class.forName("包名 . 類名");

        b、Class<類名> c=類名 . class;

        c、Class<? extends 類名> c=new 類名( ). getClass( );

        1、擷取屬性   

            Field [ ] fs=c.getDeclaredFields( );包括私有的>>差別于 Field [ ] fs=c.getFields( );獲得屬性不包括私有的。

            f.setAccessible(true);設定通路權限 ,也可通過安全管理器設定 System.setSecurityManager(new SecurityManager);

初學JavaSE筆記——(十八)反射

        2、擷取方法     

            Method [ ] m=c.getDeclaredMethods( ); 

            Method類的invoke( )調用方法

初學JavaSE筆記——(十八)反射

        3、獲得構造器

            Constructor cr=c.getDeclaredConstructor(參數類型.class);

            cr.newInstance(傳值);

        4、獲得注解

            Annotation [ ] an=c.getDeclaredAnnotations( );

            Arrays.stream( an ) . forEach( System.out ::println);

            用反射獲得 子類 繼承父類注解:

            Class<子類名> cs=子類名 . class;

            Annotation [ ] ans=cs . getField( "屬性名") . getAnnotations( );//不用getDeclaredAnnotations( )

            Arrays.stream( ans) . forEach( System.out ::println);

三、注解

        @Overridec  重寫

        @FunctionalInterface  函數式接口

        @Deprecated  已過時、過期

        @SuppressWarnings  鎮壓警告  -all    rawtypes、unused  原生類型,變量聲明了,沒有使用    unchecked 沒有進行類型檢查    serial 版本号

        自定義注解:@interface 注解名{ public/預設  類型  成員名( )  default  預設值;}

        Java元注解:@Target(ElementType . xxx),ElementType:CONSTRUCTOR 構造方法聲明;FIELD字段聲明(包括枚舉常量);LOCAL_VARIABLE 局部變量聲明;METHOD 方法聲明;PACKAGE 包聲明;PARAMETER 參數聲明;TYPE 類、接口(包括注釋類型)或枚舉聲明。

                            @Retention( )注解保留時間,RetentionPolicy . SOURCE/CLASS/RUNTIME

                            @Inherited( )子類可以繼承類 類型聲明時的注解

                            @Documented( )在生成的javadoc指令的API文檔中顯示注解資訊