Java中的反射與註解

        //Java中的反射
        //Java反射機制是指在運行狀態中
        //
        //對於任意一個類,都能知道這個類的所有屬性和方法;
        //對於任何一個對象,都能夠調用它的任何一個方法和屬性;

        //這樣動態獲取新的以及動態調用對象方法的功能就叫做反射。
        //反射機制的相關類
        //
        //Class         代表類實類
        //Field         代表類的成員變量
        //Method        代表類方法
        //Constructor   代表類的構造函數

        Class clz = ContentBean.class;
        try {//獲得公有屬性
            Field field = clz.getField("content");
            System.out.println("field = " + field.getName());
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        //獲得所有公有屬性
        Field[] fields = clz.getFields();
        for (Field f :
                fields) {
            System.out.println("field = " + f.getName());
        }
        System.out.println("_____________________________________________________________");
        try {//獲得某個類的屬性
            Field declaredField = clz.getDeclaredField("author");
            System.out.println("修飾符:" + Modifier.toString(declaredField.getModifiers())
                    + "  declaredField = " + declaredField.getName());
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        //獲得所有屬性
        Field[] declaredFields = clz.getDeclaredFields();
        for (Field df :
                declaredFields) {
            System.out.println("修飾符:" + Modifier.toString(df.getModifiers())
                    + "  declaredField = " + df.getName());
        }
        System.out.println("_____________________________________________________________");
        //獲得與參數匹配的公有註解對象
        Annotation annotation = clz.getAnnotation(Deprecated.class);
        if (annotation != null)
        System.out.println("annotation:" + annotation.annotationType().getName());
        //獲得所有公有註解對象
        Annotation[] annotations = clz.getAnnotations();
        for (Annotation a :
                annotations) {
            System.out.println("修飾符:" + Modifier.toString(a.annotationType().getModifiers()) + "  a = " + annotation.annotationType().getName());
        }
        System.out.println("_____________________________________________________________");
        //獲得某個匹配的註解對象
        Annotation declaredAnnotation = clz.getDeclaredAnnotation(Deprecated.class);
        if (declaredAnnotation != null)
        System.out.println("declaredAnnotation:" + declaredAnnotation.annotationType().getName());
        //獲得所有註解對象
        Annotation[] declaredAnnotations = clz.getDeclaredAnnotations();
        for (Annotation da:
             declaredAnnotations) {
            System.out.println("修飾符:" + Modifier.toString(da.annotationType().getModifiers()) + "  da:" + da.annotationType().getName());
        }
        System.out.println("_____________________________________________________________");
        //獲得某個參數類型匹配的公有構造函數
        try {
            Constructor constructor = ContentBean.class.getConstructor();
            System.out.println("constructor = " + constructor.getName());
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        //獲得所有公有構造函數
        Constructor[] constructors = ContentBean.class.getConstructors();
        for (Constructor c :
                constructors) {
            System.out.println("修飾符:" + Modifier.toString(c.getModifiers()) + "  c:" + c.getName());
        }
        System.out.println("_____________________________________________________________");
        //獲得某個參數類型匹配的構造函數
        try {
            Constructor dc = ContentBean.class.getDeclaredConstructor();
            System.out.println("dc = " + dc.getName());
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        //獲得所有構造函數
        Constructor[] dcs = ContentBean.class.getDeclaredConstructors();
        for (Constructor dc: dcs) {
            System.out.println("修飾符:" + Modifier.toString(dc.getModifiers()));
            System.out.println("所有參數:");
            Parameter[] parameters = dc.getParameters();
            for (Parameter p :
                    parameters) {
                System.out.println("修飾符 = " + p.getType().getSimpleName() + " p = " + p.getName());
            }
         }
        System.out.println("_____________________________________________________________");
        //獲得某個參數類型與函數名稱匹配的函數
        try {
            Method method = ContentBean.class.getMethod("getName");
            System.out.println("method = " + method.getName() + "    " + method.getReturnType().getSimpleName());
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        //...........省略getMethods()、getDeclaredMethod(...)、getDeclaredMethods()...........
        System.out.println(clz.isAnnotation());//是否是註解類型
        System.out.println(clz.isAnnotationPresent(Deprecated.class));//是否被指定註解類型修飾
        System.out.println(clz.isAnonymousClass());//是否是匿名類
        System.out.println(clz.isArray());//是否是數組
        System.out.println(clz.isEnum());//是否是枚舉類
        System.out.println(clz.isInterface());//是否是接口類
        System.out.println(clz.isLocalClass());//是否是局部類
        System.out.println(clz.isMemberClass());//是否是內部類

        //Field類
        //equals(object):屬性與obj相等則返回true
        //get(object):獲得obj中對應的屬性值
        //set(object, value);設置obj中對應屬性值
        ContentBean c = new ContentBean();
        c.setAuthor("測試");
        try {
            Field field = clz.getDeclaredField("author");
            field.setAccessible(true);
            System.out.println("author = " + field.get(c));
            field.set(c, "內容變了");
            System.out.println("author = " + field.get(c));
        }  catch (IllegalAccessException | NoSuchFieldException e) {
            e.printStackTrace();
        }

        //Method類
        //invoke(obj, args...)
        try {
            Method method = clz.getDeclaredMethod("setAuthor", String.class);
            method.invoke(c, "內容又變了");
            Method method2 = clz.getDeclaredMethod("getAuthor");
            System.out.println(method2.invoke(c));
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }

        //Constructor類
        //newInstance方法
        try {
            Constructor constructor = clz.getDeclaredConstructor(String.class, String.class);
            constructor.setAccessible(true);
            ContentBean cb = (ContentBean)constructor.newInstance("dragon", "龍博");
            System.out.println(cb.getName());
            System.out.println(cb.getAuthor());
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }

        //正確構造反射的步驟
        try {
            Class<?> className = Class.forName("com.dragon.devl.test.ContentBean");
            //獲取到類對象後,自行決定反射其內部哪些方法,比如反射setName方法
            Method method = className.getDeclaredMethod("setName", String.class);
            //獲取到方法對象後,需要構建對應的類實例,纔可以反射該方法
            Constructor constructor = className.getDeclaredConstructor();
            //constructor.setAccessible(true);無參構造函數是public類型,所以不需要設置權限
            Object obj = constructor.newInstance();//調用該構造方法獲取對象
            method.invoke(obj, "測試");//調用setName方法。

            //最後我們輸出數據
            Method getMethod = className.getDeclaredMethod("getName");
            System.out.println(getMethod.invoke(obj));

            //如果只是調用靜態方法,則不需要構造實例,直接使用method.invoke(null, args)調用
            Method staticMethod = className.getDeclaredMethod("setDesc", String.class);
            staticMethod.invoke(null, "設置靜態屬性值");
            Method getStaticMethod = className.getDeclaredMethod("getDesc");
            System.out.println(getStaticMethod.invoke(null));
            System.out.println(ContentBean.getDesc());
        } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {///由於可能會出現找不到類的情況,所以需要捕獲異常
            e.printStackTrace();
        }

Java註解

Annotation(註解)就是Java提供了一種源程序中的元素關聯任何信息或者任何元數據(metadata)的途徑和方法。

Annotation是被動的元數據,永遠不會有主動行爲

//自定義註解,使用@interface表示這是一個註解,Annotation只有成員變量,沒有方法
//Annotation的成員變量在Annotation中以無形參的方法形式來聲明,其方法名定義了該成員變量的名字,其返回值定義了該成員變量的類型
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
@Documented
@Inherited
public @interface BindContent {
    String content() default "nothing";
    boolean canBeNull() default false;
}
//在自定義註解內部使用的註解稱之爲元註解
//@Retention 用來標記自定義註解的有效範圍
//1、RetentionPolicy.SOURCE:只在源代碼中保留,一般是用來增加代碼的理解性或者幫助代碼檢查之類的,例如override
//2、RetentionPolicy.CLASS:默認值,把註解保留到編譯後的字節碼文件中,但運行時無法得到
//3、RetentionPolicy.RUNTIME:保留到編譯後的字節碼文件中,同時也能在運行時獲取。

//@Target:指定Annotation用於修飾哪些程序元素
//內部包含一個value[]成員變量
//允許傳入以下值
//ElementType.TYPE:能修飾類、接口或枚舉類
//ElementType.FIELD:修飾成員變量
//ElementType.METHOD:修飾方法
//ElementType.PARAMETER:修飾參數
//ElementType.CONSTRUCTOR:修飾構造器
//ElementType.LOCAL_VARIABLE:修飾局部變量
//ElementType.ANNOTATION_TYPE:修飾註解
//ElementType.PACKAGE:修飾包

//@Documented表示可以在javadoc中被找到
//@Interited:表示註解裏的內容可以被子類繼承,只針對class類

//類繼承關係中,子類會繼承父類使用的註解中被@Inherited修飾的註解
//
//接口繼承關係中@Inherited的作用
//
//接口繼承關係中,子接口不會繼承父接口中的任何註解,不管父接口中使用的註解有沒有被@Inherited修飾
//
//類實現接口關係中@Inherited的作用
//
//類實現接口時不會繼承任何接口中定義的註解

然後通過反射來獲取對應的註解內容

@BindContent(content = "Class desc")
public class AnnotationTesting {

    @BindContent()
    public String content;

    public void printInfo() {
        System.out.println(content);
    }

    public static void main(String[] args) {
        try {
            Class c = Class.forName("com.dragon.devl.test.AnnotationTesting");
            AnnotationTesting annotationTesting = (AnnotationTesting)c.newInstance();
            Field[] fields = c.getDeclaredFields();
            for (Field f :
                    fields) {
                if (f.isAnnotationPresent(BindContent.class)) {
                    BindContent bc = f.getAnnotation(BindContent.class);
                    f.set(annotationTesting, bc.content());
                }
            }
            annotationTesting.printInfo();
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章