成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

反射(Reflection)

LMou / 1243人閱讀

摘要:裝載類的裝載是通過類加載器完成的,加載器將文件的字節(jié)碼文件裝入的方法區(qū),并且在堆區(qū)創(chuàng)建描述這個類的對象。通過指定的對象來實例化對象取得父指定的構(gòu)造類型給傳入?yún)?shù)賦初值實例化反射操作獲得某個類的所有的字段,包括父類。

什么是反射

反射就是在運(yùn)行時把 Java 類中的各種成分映射成相應(yīng)的 Java 類(Method、Annotation等),可以動態(tài)得獲取所有的屬性以及動態(tài)調(diào)用任意一個方法。

this
class A{
    public A(){
        System.out.println(this.toString() + ";;;;" + this.getClass().getName());
    }
}

class B extends A{
    public B() {
        System.out.println(this.toString() + ";;;;" + super.getClass().getName());
    }
}

public class C extends B{
    public C() {
        System.out.println(this.toString() + ";;;;" + this.getClass().getName());
    }
    
    public static void main(String[] args) {
        C c = new C();        
    }
    
}

輸出結(jié)果:
test.C@33b7b32c;;;;test.C
test.C@33b7b32c;;;;test.C
test.C@33b7b32c;;;;test.C

可見this是基于運(yùn)行時,this的物理內(nèi)存地址都是C。

Class概念

Class類是繼承Type的。

數(shù)組屬于被映射為 Class 對象的一個類,具有相同元素類型和維數(shù)的數(shù)組都共享該 Class 對象?;镜?Java 數(shù)據(jù)類型和關(guān)鍵字 void 也表示為 Class 對象。
Class 沒有公共構(gòu)造方法。Class 對象是在加載類時由類加載器中的 defineClass 方法自動構(gòu)造的。
裝載:
類的裝載是通過類加載器完成的,加載器將*.class文件的字節(jié)碼文件裝入JVM的方法區(qū),并且在堆區(qū)創(chuàng)建描述這個類的java.lang.Class對象。?但是同一個類只會被類裝載器裝載一遍。
連接:
連接就是將已經(jīng)讀入到內(nèi)存的類的二進(jìn)制數(shù)據(jù)合并到虛擬機(jī)的運(yùn)行時環(huán)境中去,分為校驗,準(zhǔn)備,解析這3個階段。校驗一般為字節(jié)碼合法性驗證,還有語義檢查等;準(zhǔn)備就是為靜態(tài)變量分配內(nèi)存空間,并設(shè)置默認(rèn)值;解析指類的二進(jìn)制數(shù)據(jù)中的符號引用替換為直接引用(指針)。

Class.forName(ClassName).newInstance() //類實例化,默認(rèn)用的空參構(gòu)造函數(shù)。

//通過指定的Constructor對象來實例化對象
public?static?void?main(String[]?args)?{??
   try?{??
???????????Class?demo = Class.forName("mypackage.Tests");?//getSuperclass() 取得父class????????
???????????Class[]?cl = {int.class, int.class};??//指定?Constructor的構(gòu)造類型
???????????Constructor?con = demo.getConstructor(cl);??????????????
???????????Object[]?x = {new?Integer(33),new?Integer(67)};??//給傳入?yún)?shù)賦初值??
???????????Object?obj = con.newInstance(x);??//實例化??
???????}?catch?(Exception?e)?{??
???????????
???????}??
}??

class?Tests{??
????public?Tests(int?x, int?y){??
???????System.out.println(x+"????"+y);??
????}??
}

反射API操作
Class demo = Class.forName("wangliqiu.test.reflect.MyTest");
Field[] fields = demo.getDeclaredFields();
/*
 * getFields()獲得某個類的所有public的字段,包括父類。?
 * getDeclaredFields()獲得某個類的public、private和proteced的字段,但是不包括父類的申明字段。?
 * 同樣還有g(shù)etConstructors()和getDeclaredConstructors();getMethods()和getDeclaredMethods()。
 */
for (Field field : fields) {
    field.setAccessible(true);// 強(qiáng)制訪問
    // 屬性
    System.out.println("Field: " + field.getName());
    // 權(quán)限修飾符
    int mo = field.getModifiers();
    System.out.println("Modifier: " + Modifier.toString(mo));
    // 屬性類型
    Class classType = field.getType();
    System.out.println("Type: " + classType.getName());
}

Class superClass = demo.getSuperclass();// 僅獲取父類
System.out.println("getSuperclass: " + superClass);
Type superType = demo.getGenericSuperclass();// 獲取完整的父類(帶有泛型參數(shù))
System.out.println("getGenericSuperclass: " + superType);
// ParameterizedType參數(shù)化類型,即泛型
// getActualTypeArguments獲取類型的參數(shù)類型,泛型參數(shù)可能有多個
Type[] types = ((ParameterizedType) superType).getActualTypeArguments();
for (Type type : types) {
    System.out.println("getActualTypeArguments: " + type);
}

// 可能存在同名但不同參數(shù)個數(shù)或參數(shù)類型的方法,所以getMethod()的方法特征簽名要全面。
Method method = demo.getMethod("justTest", String.class, int.class);
method.invoke(demo.newInstance(), "wangliqiu", 20);

public void justTest(String name, int age) {
    System.out.println(name + "====" + age);
}

ClassLoader

1)Bootstrap ClassLoader?用c++編寫,引導(dǎo)作用。
2)Extension ClassLoader?用java編寫,用來進(jìn)行擴(kuò)展類的加載,一般對應(yīng)的是jrelibext目錄中的類
3)AppClassLoader?用java編寫,加載classpath指定的類,是最常用的加載器。

在加載類時,每個類加載器會先將加載類的任務(wù)交給其parent,如果parent找不到,再由自己負(fù)責(zé)加載。所以加載順序如下圖,若都找不到,會拋出NoClassDefFoundError。

// Bootstrap Loader會加載系統(tǒng)參數(shù)sun.boot.class.path指定位置中的文件
System.out.println(System.getProperty("sun.boot.class.path"));
// ExtClassLoader會加載系統(tǒng)參數(shù)java.ext.dirs指定位置中的文件
System.out.println(System.getProperty("java.ext.dirs"));
// AppClassLoader會加載系統(tǒng)參數(shù)java.class.path指定位置中的文件,即Classpath路徑
System.out.println(System.getProperty("java.class.path"));

/*
 * java.exe啟動會嘗試找到JRE安裝目錄的jvm.dll,接著啟動JVM ,產(chǎn)生Bootstrap Loader,Bootstrap Loader會加載
 * ExtClassLoader,并設(shè)定ExtClassLoader的parent為Bootstrap Loader。接著Bootstrap
 * Loader會加載AppClassLoader,并將AppClassLoader的parent設(shè)定為Extended Loader。
 */
ClassLoader loader = this.getClass().getClassLoader();
System.out.println(loader.getClass().getName());

// This method will return null if this class was loaded by the bootstrap class loader.
ClassLoader loaderloader = loader.getClass().getClassLoader();
System.out.println(loaderloader);

ClassLoader parentLoader = loader.getParent();
System.out.println(parentLoader.getClass().getName());

// This method will return null if this class loader"s parent is the bootstrap class loader.
ClassLoader GrandLoader = parentLoader.getParent();
System.out.println(GrandLoader);

注:
Class.forName除了將class文件加載到j(luò)vm中之外,還會執(zhí)行類中的static塊。而classLoader只將*.class文件加載到j(luò)vm中,不會執(zhí)行static塊,只有在newInstance才會去執(zhí)行static塊。Class.forName(name, initialize, loader)帶參函數(shù)也可控制是否加載static塊。

類加載及初始化過程

類加載:Bootstrap Loader -> ExtClassLoader, Bootstrap Loader -> AppClassLoader?

靜態(tài)代碼塊初始化?

鏈接

a) 驗證:是否符合java規(guī)范?
b) 準(zhǔn)備:默認(rèn)初始值?(如boolean為false,int為0等)
c) 解析:符號引用轉(zhuǎn)為直接引用,解析地址?

初始化?

a) 賦值:類中屬性的初始值?
b) 構(gòu)造:構(gòu)造函數(shù)?

@interface

@Retention、@Target、@Documented、@Inherited可以用來修飾注解,是注解的注解,稱為元注解。

@Retention

Retention注解有一個屬性value,是Enum RetentionPolicy枚舉類型,RetentionPolicy有3個值:CLASS? RUNTIME?? SOURCE。
@Retention(RetentionPolicy.SOURCE ) 表示注解的信息只留在源文件中,不參與編譯;
@Retention(RetentionPolicy.CLASS) 表示注解的信息被保留在*.class文件(字節(jié)碼文件)中(程序編譯中),但不會被JVM讀??;
@Retention(RetentionPolicy.RUNTIME ) 表示注解的信息被保留在*.class文件(字節(jié)碼文件)中,也會被JVM保留在運(yùn)行時。

例如:

@Retention(RetentionPolicy.SOURCE )  
public @interface Override  
 
@Retention(RetentionPolicy.SOURCE )  
public @interface SuppressWarnings  
 
@Retention(RetentionPolicy.RUNTIME )  
public @interface Deprecated 

@Target

例子:

@Retention(RetentionPolicy.RUNTIME)  
@interface Test{
    String value();
}

@Retention(RetentionPolicy.RUNTIME)  
@interface MyAnnotation{  
    String hello() default "shanghai";  
    String world();    //world()沒有默認(rèn)值,添加注釋MyAnnotation時, world屬性必須輸入?yún)?shù)
    int[] array() default { 2, 4, 5, 6 };      
    Test lannotation() default @Test(value = "ffffd");  
    Class style() default String.class;  
}

@MyAnnotation(hello = "beijing", world="class", array={1, 2, 3}, style= int.class)  
class MyTest{  
    @MyAnnotation(world = "method", lannotation=@Test(value="baby"))  
    @Deprecated  
    @SuppressWarnings("")
    public void output(String str, int i){  
        System.out.println("str:" + str +"   int:" + i);  
    }  
}

public class MyReflection{  
    public static void main(String[] args) throws Exception{  
        
        MyAnnotation myClassAnnotation = MyTest.class.getAnnotation(MyAnnotation.class);
        System.out.println("hello:" + myClassAnnotation.hello() + "    world:" + myClassAnnotation.world());
        
        MyAnnotation myMethodAnnotation = method.getAnnotation(MyAnnotation.class);                      
        System.out.println("hello:" + myMethodAnnotation.hello() + "   world:" + myMethodAnnotation.world() +
                "    @Test.value:" + myMethodAnnotation.lannotation().value()     );
        
        Annotation[] annotations = method.getAnnotations();  //獲得方法的所有運(yùn)行時的注釋
        for (Annotation annotation : annotations) {  
            System.out.println(annotation.annotationType().getName());  
        }  
   }  
} 

輸出:
str:gogo int:9999
hello:beijing world:class
hello:shanghai world:method @Test.value:baby
test.MyAnnotation
java.lang.Deprecated
@SuppressWarnings("")沒有顯示,可見只有運(yùn)行時的注釋才會執(zhí)行。

@Documented

由@Documented修飾的注解可以在javadoc中顯示。

@Documented
public @interface Column {
     ....
}
@Column     //@Column將在javadoc中顯示
Public Demo demo {
....
}

@Inherited

子類可以繼承父類的帶有@Inherited修飾的注解。

@Inherited
public @interface Column {
     ....
}
@Column 
Public class Super {
    ....
}

Public class Sub extends Super {
    ....
}

則Sub繼承@Column注解。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/67269.html

相關(guān)文章

  • 從yii2框架中的di容器源碼中了解反射的作用

    摘要:反射簡介參考官方簡介的話,具有完整的反射,添加了對類接口函數(shù)方法和擴(kuò)展進(jìn)行反向工程的能力。此外,反射提供了方法來取出函數(shù)類和方法中的文檔注釋。 反射簡介 參考官方簡介的話,PHP 5 具有完整的反射 API,添加了對類、接口、函數(shù)、方法和擴(kuò)展進(jìn)行反向工程的能力。 此外,反射 API 提供了方法來取出函數(shù)、類和方法中的文檔注釋。 YII2框架中示例 對于yii2框架,應(yīng)該都知道di容器,...

    dantezhao 評論0 收藏0
  • Essential SQLAlchemy2th學(xué)習(xí)筆記之反射Reflection

    摘要:基于反射對象進(jìn)行查詢模塊反射這里我們不再使用而是使用擴(kuò)展模塊的獲取所有的對象名獲取表對象進(jìn)行操作反射關(guān)聯(lián)關(guān)系可以反射并建立表之間的但是建立關(guān)聯(lián)列的命名為例如關(guān)于更多信息請詳細(xì)參看官方文檔 示例數(shù)據(jù)庫下載:http://chinookdatabase.codepl...在SQLALchemy中,我們使用反射技術(shù)來獲取相關(guān)database schema信息,如tables,views,in...

    NSFish 評論0 收藏0
  • 【modernPHP專題(2)】反射機(jī)制Reflection

    摘要:簡介是才有的新功能,它是用來導(dǎo)出或提取出關(guān)于類方法屬性參數(shù)等的詳細(xì)信息,包括注釋。 簡介 PHP Reflection API是PHP5才有的新功能,它是用來導(dǎo)出或提取出關(guān)于類、方法、屬性、參數(shù)等的詳細(xì)信息,包括注釋。 class Reflection { } interface Reflector { } class ReflectionException extends Exce...

    mrli2016 評論0 收藏0
  • Java 反射(Reflection)

    摘要:效率運(yùn)行效率使用反射減低程序的運(yùn)行效率。開發(fā)效率由于反射運(yùn)用到各個框架中,大大加快了開發(fā)的效率。 反射的核心就是Class對象,每一個類被jvm加載都會有一個對應(yīng)的class對象,這個class對象包含了這個類的結(jié)構(gòu)信息,反射就是會通過反射api反復(fù)操作這個class對象(屬性,方法,注解,構(gòu)造器,泛型),但是反射會降低程序的運(yùn)行效率,比普通方法要慢30倍,通過setAccessble...

    shengguo 評論0 收藏0
  • Reflection:Java反射機(jī)制的應(yīng)用場景

    近期在維護(hù)公司項目的時候遇到一個問題,因為實體類中的 set 方法涉及到了業(yè)務(wù)邏輯,因此在給對象賦值的過程中不能夠使用 set 方法,為了實現(xiàn)功能,所以采用了反射的機(jī)制給對象屬性賦值,借此機(jī)會也了解了反射的一些具體用法和使用場景,分以下兩點對反射進(jìn)行分析: 反射的優(yōu)勢和劣勢 反射的應(yīng)用場景 反射的優(yōu)勢和劣勢 ??個人理解,反射機(jī)制實際上就是上帝模式,如果說方法的調(diào)用是 Java 正確的打開方式...

    浠ラ箍 評論0 收藏0
  • ES6中的代理(Proxy)和反射Reflection

    摘要:代理和反射的定義調(diào)用可常見代替其它目標(biāo)對象的代理,它虛擬化了目標(biāo),所以二者看起來功能一致。代理可攔截引擎內(nèi)部目標(biāo)的底層對象操作,這些底層操作被攔截后會觸發(fā)響應(yīng)特定操作的陷阱函數(shù)。 代理和反射的定義 調(diào)用 new Proxy() 可常見代替其它目標(biāo) (target) 對象的代理,它虛擬化了目標(biāo),所以二者看起來功能一致。 代理可攔截JS引擎內(nèi)部目標(biāo)的底層對象操作,這些底層操作被攔截后會觸發(fā)...

    Markxu 評論0 收藏0

發(fā)表評論

0條評論

LMou

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<