java基礎之反射(reflect)

上周記錄了java基礎之注解(Annotation),這周他的好基友“反射”如約而至(明明是姍姍來遲~)。

反射的基本概念

反射機制是在運行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調(diào)用它的任意一個方法和屬性;這種動態(tài)獲取的信息以及動態(tài)調(diào)用對象的方法的功能稱為java語言的反射機制。

反射的基石:class類

Class類的各個實例對象分別對應各個類在內(nèi)存中的字節(jié)碼,例如TestModel類的字節(jié)碼,ArrayList類的字節(jié)碼,等等。

一個類被類加載器加載到內(nèi)存中,占用一片存儲空間,這個空間里面的內(nèi)容就是類的字節(jié)碼,不同的類的字節(jié)碼是不同的,所以他們在內(nèi)存中的內(nèi)容是不同的,這一個個空間可分別用一個個對象來表示,這些對象顯然具有相同的類型,這個類型就是Class類型

這里一定要分清一個對象的Class類型和對象的內(nèi)容。 兩個不同的對象是可以有相同的Class類型的。
比如說: 下面兩個字符串明顯不是同一個的對象,但他們的Class類型是一樣的:java.lang.String

String str1 = "abc";//字符串1
String str2 = "abcd";//字符串2

反射常用方法

實例化Class類對象

Class clazz = Class.forName("java.lang.String");
Class clazz = new String().getClass();
Class clazz = String.class;

Class中的Constructor類,實例化一個對象

/**獲取String對象的所有構(gòu)造方法*/
Constructor[] constructors = Class.forName("java.lang.String").getConstructors();

/**獲取String默認的構(gòu)造方法生成String對象*/
String str = String.class.newInstance();

/**獲取String對象指定的構(gòu)造方法(通過方法的參數(shù)類型,傳遞參數(shù)的Class對象)*/
Constructor constructor = String.class.getConstructor(StringBuffer.class);
String str = (String) constructor.newInstance(new StringBuffer("abc"));

Class中的Field類

/**獲取clazz這個Class的所有字段*/
Field[] fields = clazz.getDeclaredFields();

//獲取clazz的字段名為“X”的字段
//getField方法只能獲取到public字段,getDeclaredField可以獲取到所有的字段
Field field = clazz.getDeclaredField("x");

//對于private修飾的字段需要設置Accessible為true
field.setAccessible(true);

//設置和獲取field的屬性
 field.set(testModel, (String)name.value());
 field.get(obj);

//獲取字段的類型
 field.getGenericType()

//判斷是否有TestAnnotationName注解
field.isAnnotationPresent(TestAnnotationName.class)
//獲取字段上的注解
 field.getAnnotation(annotationClass)

Class中的Method類

獲取Method的方法和獲取field的方法基本一致

//獲取所有方法
Method[] methods = clazz.getDeclaredMethods();

//獲取對應方法
Method methodCharAt = clazz.getMethod("charAt", int.class);

//調(diào)用方法
methodCharAt.invoke(object,18);

獲取一個對象的父類與實現(xiàn)的接口

 // 取得父類
 Class<?> parentClass = clazz.getSuperclass();
 // 獲取所有的接口
 Class<?> intes[] = clazz.getInterfaces();

使用反射解析注解

終于說到注解了

聲明注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotationAge{
    int value() default 18;
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotationName{
    String value() default "aclululu";
}

設置注解

public class TestModel {

    @TestAnnotationName
    private String name;

    @TestAnnotationAge
    private int age;

    /**省略getter setter方法**/
}

解析注解

public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
    TestModel testModel = new TestModel();
    System.out.println(testModel.toString());
    System.out.println("通過反射機制將注解信息設置給Model...");
    Class clazz = TestModel.class;
    Field[] fields = clazz.getDeclaredFields();
    for(Field field :fields){
        if(field.isAnnotationPresent(TestAnnotationName.class)){
            TestAnnotationName name = (TestAnnotationName) field.getAnnotation(TestAnnotationName.class);
            field.setAccessible(true);
            field.set(testModel, (String)name.value());
        }
        else if(field.isAnnotationPresent(TestAnnotationAge.class)){
             TestAnnotationAge age= (TestAnnotationAge) field.getAnnotation(TestAnnotationAge.class);
             field.setAccessible(true);
             field.set(testModel, (int)age.value());
        }
    }
    
    System.out.println(testModel.toString());
}

輸出結(jié)果

TestModel [age=0, name=null]
通過反射機制將注解信息設置給Model...
TestModel [age=18, name=aclululu]
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容