91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java基礎13:反射詳解

發布時間:2020-08-10 08:20:09 來源:ITPUB博客 閱讀:184 作者:a724888 欄目:編程語言

更多內容請關注微信公眾號【Java技術江湖】

這是一位阿里 Java 工程師的技術小站,作者黃小斜,專注 Java 相關技術:SSM、SpringBoot、MySQL、分布式、中間件、集群、Linux、網絡、多線程,偶爾講點Docker、ELK,同時也分享技術干貨和學習經驗,致力于Java全棧開發!(關注公眾號后回復”資料“即可領取 3T 免費技術學習資源以及我我原創的程序員校招指南、Java學習指南等資源)

Java基礎13:反射詳解cdn.xitu.io/2019/4/6/169f1735fd0d1d16?w=900&h=500&f=jpeg&s=109856"> 本節主要介紹Java反射的原理,使用方法以及相關的技術細節,并且介紹了關于Class類,注解等內容。

具體代碼在我的GitHub中可以找到

https://github.com/h3pl/MyTech

文章首發于我的個人博客:

https://h3pl.github.io/2018/05/01/javase13

更多關于Java后端學習的內容請到我的CSDN博客上查看:

https://blog.csdn.net/a724888

回顧:什么是反射?

反射(Reflection)是Java 程序開發語言的特征之一,它允許運行中的 Java 程序獲取自身的信息,并且可以操作類或對象的內部屬性。 Oracle官方對反射的解釋是

Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions.

The API accommodates applications that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class. It also allows programs to suppress default reflective access control.

簡而言之,通過反射,我們可以在運行時獲得程序或程序集中每一個類型的成員和成員的信息。

程序中一般的對象的類型都是在編譯期就確定下來的,而Java反射機制可以動態地創建對象并調用其屬性,這樣的對象的類型在編譯期是未知的。所以我們可以通過反射機制直接創建對象,即使這個對象的類型在編譯期是未知的。

反射的核心是JVM在運行時才動態加載類或調用方法/訪問屬性,它不需要事先(寫代碼的時候或編譯期)知道運行對象是誰。

Java反射框架主要提供以下功能:

1.在運行時判斷任意一個對象所屬的類;

2.在運行時構造任意一個類的對象;

3.在運行時判斷任意一個類所具有的成員變量和方法(通過反射甚至可以調用private方法);

4.在運行時調用任意一個對象的方法

重點:是運行時而不是編譯時

反射的主要用途

很多人都認為反射在實際的Java開發應用中并不廣泛,其實不然。

當我們在使用IDE(如Eclipse,IDEA)時,當我們輸入一個對象或類并想調用它的屬性或方法時,一按點號,編譯器就會自動列出它的屬性或方法,這里就會用到反射。

反射最重要的用途就是開發各種通用框架。

很多框架(比如Spring)都是配置化的(比如通過XML文件配置JavaBean,Action之類的),為了保證框架的通用性,它們可能需要根據配置文件加載不同的對象或類,調用不同的方法,這個時候就必須用到反射——運行時動態加載需要加載的對象。

舉一個例子,在運用Struts 2框架的開發中我們一般會在struts.xml里去配置Action,比如:

<action name="login"
               class="org.ScZyhSoft.test.action.SimpleLoginAction"
               method="execute">
           <result>/shop/shop-index.jsp</result>
           <result name="error">login.jsp</result>
       </action>

配置文件與Action建立了一種映射關系,當View層發出請求時,請求會被StrutsPrepareAndExecuteFilter攔截,然后StrutsPrepareAndExecuteFilter會去動態地創建Action實例。

——比如我們請求login.action,那么StrutsPrepareAndExecuteFilter就會去解析struts.xml文件,檢索action中name為login的Action,并根據class屬性創建SimpleLoginAction實例,并用invoke方法來調用execute方法,這個過程離不開反射。

對與框架開發人員來說,反射雖小但作用非常大,它是各種容器實現的核心。而對于一般的開發者來說,不深入框架開發則用反射用的就會少一點,不過了解一下框架的底層機制有助于豐富自己的編程思想,也是很有益的。

反射的基礎:關于Class類

更多關于Class類和Object類的原理和介紹請見上一節

1、Class是一個類,一個描述類的類(也就是描述類本身),封裝了描述方法的Method,描述字段的Filed,描述構造器的Constructor等屬性

2、對象照鏡子后(反射)可以得到的信息:某個類的數據成員名、方法和構造器、某個類到底實現了哪些接口。

3、對于每個類而言,JRE 都為其保留一個不變的 Class 類型的對象。一個Class對象包含了特定某個類的有關信息。

4、Class 對象只能由系統建立對象

5、一個類在 JVM 中只會有一個Class實例

//總結一下就是,JDK有一個類叫做Class,這個類用來封裝所有Java類型,包括這些類的所有信息,JVM中類信息是放在方法區的。
//所有類在加載后,JVM會為其在堆中創建一個Class<類名稱>的對象,并且每個類只會有一個Class對象,這個類的所有對象都要通過Class<類名稱>來進行實例化。
//上面說的是JVM進行實例化的原理,當然實際上在Java寫代碼時只需要用 類名稱就可以進行實例化了。
public final class Class<T> implements java.io.Serializable,
                          GenericDeclaration,
                          Type,
                          AnnotatedElement {
虛擬機會保持唯一一
            //通過類名.class獲得唯一的Class對象。
            Class<UserBean> cls = UserBean.class;
            //通過integer.TYPEl來獲取Class對象
            Class<Integer> inti = Integer.TYPE;
          //接口本質也是一個類,一樣可以通過.class獲取
            Class<User> userClass = User.class;

反射的基本運用

上面我們提到了反射可以用于判斷任意對象所屬的類,獲得Class對象,構造任意一個對象以及調用一個對象。這里我們介紹一下基本反射功能的實現(反射相關的類一般都在java.lang.relfect包里)。

1、獲得Class對象方法有三種

(1)使用Class類的forName靜態方法:

 public static Class<?> forName(String className)
```
在JDBC開發中常用此方法加載數據庫驅動:
要使用全類名來加載這個類,一般數據庫驅動的配置信息會寫在配置文件中。加載這個驅動前要先導入jar包
```java
 Class.forName(driver);

(2)直接獲取某一個對象的class,比如:

//Class<?>是一個泛型表示,用于獲取一個類的類型。
Class<?> klass = int.class;
Class<?> classInt = Integer.TYPE;

(3)調用某個對象的getClass()方法,比如:

StringBuilder str = new StringBuilder("123");
Class<?> klass = str.getClass();

判斷是否為某個類的實例

一般地,我們用instanceof關鍵字來判斷是否為某個類的實例。同時我們也可以借助反射中Class對象的isInstance()方法來判斷是否為某個類的實例,它是一個Native方法:

==public native boolean isInstance(Object obj);==

創建實例

通過反射來生成對象主要有兩種方式。

(1)使用Class對象的newInstance()方法來創建Class對象對應類的實例。

注意:利用newInstance創建對象:調用的類必須有無參的構造器

//Class<?>代表任何類的一個類對象。
//使用這個類對象可以為其他類進行實例化
//因為jvm加載類以后自動在堆區生成一個對應的*.Class對象
//該對象用于讓JVM對進行所有*對象實例化。
Class<?> c = String.class;
//Class<?> 中的 ? 是通配符,其實就是表示任意符合泛類定義條件的類,和直接使用 Class
//效果基本一致,但是這樣寫更加規范,在某些類型轉換時可以避免不必要的 unchecked 錯誤。
Object str = c.newInstance();

(2)先通過Class對象獲取指定的Constructor對象,再調用Constructor對象的newInstance()方法來創建實例。這種方法可以用指定的構造器構造類的實例。

//獲取String所對應的Class對象
Class<?> c = String.class;
//獲取String類帶一個String參數的構造器
Constructor constructor = c.getConstructor(String.class);
//根據構造器創建實例
Object obj = constructor.newInstance("23333");
System.out.println(obj);

獲取方法

獲取某個Class對象的方法集合,主要有以下幾個方法:

getDeclaredMethods()方法返回類或接口聲明的所有方法,==包括公共、保護、默認(包)訪問和私有方法,但不包括繼承的方法==。

public Method[] getDeclaredMethods() throws SecurityException

getMethods()方法返回某個類的所有公用(public)方法,==包括其繼承類的公用方法。==

public Method[] getMethods() throws SecurityException

getMethod方法返回一個特定的方法,其中第一個參數為方法名稱,后面的參數為方法的參數對應Class的對象

public Method getMethod(String name, Class<?>... parameterTypes)

只是這樣描述的話可能難以理解,我們用例子來理解這三個方法: 本文中的例子用到了以下這些類,用于反射的測試。

//注解類,可可用于表示方法,可以通過反射獲取注解的內容。
    //Java注解的實現是很多注框架實現注解配置的基礎
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Invoke {
}

userbean的父類personbean

public class PersonBean {
private String name;
int id;
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}

}

接口user

public interface User {
    public void login ();
}

userBean實現user接口,繼承personbean

public class UserBean extends PersonBean implements User{
    @Override
    public void login() {
    }
    class B {
    }
    public String userName;
    protected int i;
    static int j;
    private int l;
    private long userId;
    public UserBean(String userName, long userId) {
        this.userName = userName;
        this.userId = userId;
    }
    public String getName() {
        return userName;
    }
    public long getId() {
        return userId;
    }
    @Invoke
    public static void staticMethod(String devName,int a) {
        System.out.printf("Hi %s, I'm a static method", devName);
    }
    @Invoke
    public void publicMethod() {
        System.out.println("I'm a public method");
    }
    @Invoke
    private void privateMethod() {
        System.out.println("I'm a private method");
    }
}

1 getMethods和getDeclaredMethods的區別

public class 動態加載類的反射 {
    public static void main(String[] args) {
        try {
            Class clazz = Class.forName("com.javase.反射.UserBean");
            for (Field field : clazz.getDeclaredFields()) {
//                field.setAccessible(true);
                System.out.println(field);
            }
            //getDeclaredMethod*()獲取的是類自身聲明的所有方法,包含public、protected和private方法。
            System.out.println("------共有方法------");
//        getDeclaredMethod*()獲取的是類自身聲明的所有方法,包含public、protected和private方法。
//            getMethod*()獲取的是類的所有共有方法,這就包括自身的所有public方法,和從基類繼承的、從接口實現的所有public方法。
            for (Method method : clazz.getMethods()) {
                String name = method.getName();
                System.out.println(name);
                //打印出了UserBean.java的所有方法以及父類的方法
            }
            System.out.println("------獨占方法------");
            for (Method method : clazz.getDeclaredMethods()) {
                String name = method.getName();
                System.out.println(name);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

2 打印一個類的所有方法及詳細信息:

public class 打印所有方法 {
    public static void main(String[] args) {
        Class userBeanClass = UserBean.class;
        Field[] fields = userBeanClass.getDeclaredFields();
        //注意,打印方法時無法得到局部變量的名稱,因為jvm只知道它的類型
        Method[] methods = userBeanClass.getDeclaredMethods();
        for (Method method : methods) {
            //依次獲得方法的修飾符,返回類型和名稱,外加方法中的參數
            String methodString = Modifier.toString(method.getModifiers()) + " " ; // private static
            methodString += method.getReturnType().getSimpleName() + " "; // void
            methodString += method.getName() + "("; // staticMethod
            Class[] parameters = method.getParameterTypes();
            Parameter[] p = method.getParameters();
            for (Class parameter : parameters) {
                methodString += parameter.getSimpleName() + " " ; // String
            }
            methodString += ")";
            System.out.println(methodString);
        }
        //注意方法只能獲取到其類型,拿不到變量名
/*        public String getName()
        public long getId()
        public static void staticMethod(String int )
        public void publicMethod()
        private void privateMethod()*/
    }
}

獲取構造器信息

獲取類構造器的用法與上述獲取方法的用法類似。主要是通過Class類的getConstructor方法得到Constructor類的一個實例,而Constructor類有一個newInstance方法可以創建一個對象實例:

public class 打印構造方法 {
    public static void main(String[] args) {
        // constructors
        Class<?> clazz = UserBean.class;
        Class userBeanClass = UserBean.class;
        //獲得所有的構造方法
        Constructor[] constructors = userBeanClass.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            String s = Modifier.toString(constructor.getModifiers()) + " ";
            s += constructor.getName() + "(";
            //構造方法的參數類型
            Class[] parameters = constructor.getParameterTypes();
            for (Class parameter : parameters) {
                s += parameter.getSimpleName() + ", ";
            }
            s += ")";
            System.out.println(s);
            //打印結果//public com.javase.反射.UserBean(String, long, )
        }
    }
}

獲取類的成員變量(字段)信息

主要是這幾個方法,在此不再贅述:

getFiled: 訪問公有的成員變量 getDeclaredField:所有已聲明的成員變量。但不能得到其父類的成員變量 getFileds和getDeclaredFields用法同上(參照Method)

public class 打印成員變量 {
    public static void main(String[] args) {
        Class userBeanClass = UserBean.class;
        //獲得該類的所有成員變量,包括static private
        Field[] fields = userBeanClass.getDeclaredFields();
        for(Field field : fields) {
            //private屬性即使不用下面這個語句也可以訪問
//            field.setAccessible(true);
            //因為類的私有域在反射中默認可訪問,所以flag默認為true。
            String fieldString = "";
            fieldString += Modifier.toString(field.getModifiers()) + " "; // `private`
            fieldString += field.getType().getSimpleName() + " "; // `String`
            fieldString += field.getName(); // `userName`
            fieldString += ";";
            System.out.println(fieldString);
            
            //打印結果
//            public String userName;
//            protected int i;
//            static int j;
//            private int l;
//            private long userId;
        }
    }
}

調用方法

當我們從類中獲取了一個方法后,我們就可以用invoke()方法來調用這個方法。invoke方法的原型為:

public Object invoke(Object obj, Object... args)
        throws IllegalAccessException, IllegalArgumentException,
           InvocationTargetException
       
public class 使用反射調用方法 {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException {
        Class userBeanClass = UserBean.class;
        //獲取該類所有的方法,包括靜態方法,實例方法。
        //此處也包括了私有方法,只不過私有方法在用invoke訪問之前要設置訪問權限
        //也就是使用setAccessible使方法可訪問,否則會拋出異常
//       // IllegalAccessException的解釋是
//        * An IllegalAccessException is thrown when an application tries
// * to reflectively create an instance (other than an array),
// * set or get a field, or invoke a method, but the currently
// * executing method does not have access to the definition of
// * the specified class, field, method or constructor.
//        getDeclaredMethod*()獲取的是類自身聲明的所有方法,包含public、protected和private方法。
//            getMethod*()獲取的是類的所有共有方法,這就包括自身的所有public方法,和從基類繼承的、從接口實現的所有public方法。
        //就是說,當這個類,域或者方法被設為私有訪問,使用反射調用但是卻沒有權限時會拋出異常。
        Method[] methods = userBeanClass.getDeclaredMethods(); // 獲取所有成員方法
        for (Method method : methods) {
            //反射可以獲取方法上的注解,通過注解來進行判斷
            if (method.isAnnotationPresent(Invoke.class)) { // 判斷是否被 @Invoke 修飾
                //判斷方法的修飾符是是static
                if (Modifier.isStatic(method.getModifiers())) { // 如果是 static 方法
                    //反射調用該方法
                    //類方法可以直接調用,不必先實例化
                    method.invoke(null, "wingjay",2); // 直接調用,并傳入需要的參數 devName
                } else {
                    //如果不是類方法,需要先獲得一個實例再調用方法
                    //傳入構造方法需要的變量類型
                    Class[] params = {String.class, long.class};
                    //獲取該類指定類型的構造方法
                    //如果沒有這種類型的方法會報錯
                    Constructor constructor = userBeanClass.getDeclaredConstructor(params); // 獲取參數格式為 String,long 的構造函數
                    //通過構造方法的實例來進行實例化
                    Object userBean = constructor.newInstance("wingjay", 11); // 利用構造函數進行實例化,得到 Object
                    if (Modifier.isPrivate(method.getModifiers())) {
                        method.setAccessible(true); // 如果是 private 的方法,需要獲取其調用權限
//                        Set the {@code accessible} flag for this object to
//     * the indicated boolean value.  A value of {@code true} indicates that
//     * the reflected object should suppress Java language access
//     * checking when it is used.  A value of {@code false} indicates
//                                * that the reflected object should enforce Java language access checks.
                        //通過該方法可以設置其可見或者不可見,不僅可以用于方法
                        //后面例子會介紹將其用于成員變量
                                            //打印結果
//            I'm a public method
// Hi wingjay, I'm a static methodI'm a private method
                    }
                    method.invoke(userBean); // 調用 method,無須參數
                    
                    
                }
            }
        }
    }
}

利用反射創建數組

數組在Java里是比較特殊的一種類型,它可以賦值給一個Object Reference。下面我們看一看利用反射創建數組的例子:

public class 用反射創建數組 {
    public static void main(String[] args) {
        Class<?> cls = null;
        try {
            cls = Class.forName("java.lang.String");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Object array = Array.newInstance(cls,25);
        //往數組里添加內容
        Array.set(array,0,"hello");
        Array.set(array,1,"Java");
        Array.set(array,2,"fuck");
        Array.set(array,3,"Scala");
        Array.set(array,4,"Clojure");
        //獲取某一項的內容
        System.out.println(Array.get(array,3));
        //Scala
    }
}

其中的Array類為java.lang.reflect.Array類。我們通過Array.newInstance()創建數組對象,它的原型是:

public static Object newInstance(Class<?> componentType, int length)
        throws NegativeArraySizeException {
        return newArray(componentType, length);
    }

而newArray()方法是一個Native方法,它在Hotspot JVM里的具體實現我們后邊再研究,這里先把源碼貼出來

private static native Object newArray(Class<?> componentType, int length)
        throws NegativeArraySizeException;

阿丙的博客園 把每一件簡單的事情做好,就是不簡單;把每一件平凡的事情做好,就是不平凡!相信自己,創造奇跡~~ 博客園首頁聯系管理 隨筆 - 441 文章 - 0 評論 - 53 注解Annotation實現原理與自定義注解例子 什么是注解? 對于很多初次接觸的開發者來說應該都有這個疑問?Annontation是Java5開始引入的新特征,中文名稱叫注解。它提供了一種安全的類似注釋的機制,用來將任何的信息或元數據(metadata)與程序元素(類、方法、成員變量等)進行關聯。為程序的元素(類、方法、成員變量)加上更直觀更明了的說明,這些說明信息是與程序的業務邏輯無關,并且供指定的工具或框架使用。Annontation像一種修飾符一樣,應用于包、類型、構造方法、方法、成員變量、參數及本地變量的聲明語句中。 ??Java注解是附加在代碼中的一些元信息,用于一些工具在編譯、運行時進行解析和使用,起到說明、配置的功能。注解不會也不能影響代碼的實際邏輯,僅僅起到輔助性的作用。包含在 java.lang.annotation 包中。

注解的用處: 1、生成文檔。這是最常見的,也是java 最早提供的注解。常用的有@param @return 等 2、跟蹤代碼依賴性,實現替代配置文件功能。比如Dagger 2依賴注入,未來java開發,將大量注解配置,具有很大用處; 3、在編譯時進行格式檢查。如@override 放在方法前,如果你這個方法并不是覆蓋了超類方法,則編譯時就能檢查出。

注解的原理: ??注解本質是一個繼承了Annotation的特殊接口,其具體實現類是Java運行時生成的動態代理類。而我們通過反射獲取注解時,返回的是Java運行時生成的動態代理對象$Proxy1。通過代理對象調用自定義注解(接口)的方法,會最終調用AnnotationInvocationHandler的invoke方法。該方法會從memberValues這個Map中索引出對應的值。而memberValues的來源是Java常量池。

元注解: java.lang.annotation提供了四種元注解,專門注解其他的注解(在自定義注解的時候,需要使用到元注解): @Documented –注解是否將包含在JavaDoc中 @Retention –什么時候使用該注解 @Target –注解用于什么地方 @Inherited – 是否允許子類繼承該注解

1.)@Retention– 定義該注解的生命周期 ● RetentionPolicy.SOURCE : 在編譯階段丟棄。這些注解在編譯結束之后就不再有任何意義,所以它們不會寫入字節碼。@Override, @SuppressWarnings都屬于這類注解。 ● RetentionPolicy.CLASS : 在類加載的時候丟棄。在字節碼文件的處理中有用。注解默認使用這種方式 ● RetentionPolicy.RUNTIME : 始終不會丟棄,運行期也保留該注解,因此可以使用反射機制讀取該注解的信息。我們自定義的注解通常使用這種方式。

2.)Target – 表示該注解用于什么地方。默認值為任何元素,表示該注解用于什么地方。可用的ElementType參數包括 ● ElementType.CONSTRUCTOR:用于描述構造器 ● ElementType.FIELD:成員變量、對象、屬性(包括enum實例) ● ElementType.LOCAL_VARIABLE:用于描述局部變量 ● ElementType.METHOD:用于描述方法 ● ElementType.PACKAGE:用于描述包 ● ElementType.PARAMETER:用于描述參數 ● ElementType.TYPE:用于描述類、接口(包括注解類型) 或enum聲明

3.)@Documented–一個簡單的Annotations標記注解,表示是否將注解信息添加在java文檔中。

4.)@Inherited – 定義該注釋和子類的關系 @Inherited 元注解是一個標記注解,@Inherited闡述了某個被標注的類型是被繼承的。如果一個使用了@Inherited修飾的annotation類型被用于一個class,則這個annotation將被用于該class的子類。

常見標準的Annotation: 1.)Override java.lang.Override是一個標記類型注解,它被用作標注方法。它說明了被標注的方法重載了父類的方法,起到了斷言的作用。如果我們使用了這種注解在一個沒有覆蓋父類方法的方法時,java編譯器將以一個編譯錯誤來警示。 2.)Deprecated Deprecated也是一種標記類型注解。當一個類型或者類型成員使用@Deprecated修飾的話,編譯器將不鼓勵使用這個被標注的程序元素。所以使用這種修飾具有一定的“延續性”:如果我們在代碼中通過繼承或者覆蓋的方式使用了這個過時的類型或者成員,雖然繼承或者覆蓋后的類型或者成員并不是被聲明為@Deprecated,但編譯器仍然要報警。 3.)SuppressWarnings SuppressWarning不是一個標記類型注解。它有一個類型為String[]的成員,這個成員的值為被禁止的警告名。對于javac編譯器來講,被-Xlint選項有效的警告名也同樣對@SuppressWarings有效,同時編譯器忽略掉無法識別的警告名。 ??@SuppressWarnings("unchecked")

自定義注解: 自定義注解類編寫的一些規則:

  1. Annotation型定義為@interface, 所有的Annotation會自動繼承java.lang.Annotation這一接口,并且不能再去繼承別的類或是接口.
  2. 參數成員只能用public或默認(default)這兩個訪問權修飾
  3. 參數成員只能用基本類型byte,short,char,int,long,float,double,boolean八種基本數據類型和String、Enum、Class、annotations等數據類型,以及這一些類型的數組.
  4. 要獲取類方法和字段的注解信息,必須通過Java的反射技術來獲取 Annotation對象,因為你除此之外沒有別的獲取注解對象的方法
  5. 注解也可以沒有定義成員, 不過這樣注解就沒啥用了 PS:自定義注解需要使用到元注解

自定義注解實例: FruitName.java

按 Ctrl+C 復制代碼

import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**

  • 水果名稱注解 */ @Target(FIELD) @Retention(RUNTIME) @Documented public @interface FruitName { String value() default ""; } 按 Ctrl+C 復制代碼

FruitColor.java

按 Ctrl+C 復制代碼

import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**

  • 水果顏色注解  / @Target(FIELD) @Retention(RUNTIME) @Documented public @interface FruitColor { / *

    • 顏色枚舉 */ public enum Color{ BLUE,RED,GREEN};

    /**

    • 顏色屬性 */ Color fruitColor() default Color.GREEN;

} 按 Ctrl+C 復制代碼

FruitProvider.java

按 Ctrl+C 復制代碼

import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**

  • 水果供應者注解  / @Target(FIELD) @Retention(RUNTIME) @Documented public @interface FruitProvider { / *

    • 供應商編號 */ public int id() default -1;

    /**

    • 供應商名稱 */ public String name() default "";

    /**

    • 供應商地址 */ public String address() default ""; } 按 Ctrl+C 復制代碼

FruitInfoUtil.java

按 Ctrl+C 復制代碼

import java.lang.reflect.Field;

/**

  • 注解處理器 */ public class FruitInfoUtil { public static void getFruitInfo(Class<?> clazz){

     String strFruitName=" 水果名稱:";
     String strFruitColor=" 水果顏色:";
     String strFruitProvicer="供應商信息:";
     
     Field[] fields = clazz.getDeclaredFields();
     
     for(Field field :fields){
         if(field.isAnnotationPresent(FruitName.class)){
             FruitName fruitName = (FruitName) field.getAnnotation(FruitName.class);
             strFruitName=strFruitName+fruitName.value();
             System.out.println(strFruitName);
         }
         else if(field.isAnnotationPresent(FruitColor.class)){
             FruitColor fruitColor= (FruitColor) field.getAnnotation(FruitColor.class);
             strFruitColor=strFruitColor+fruitColor.fruitColor().toString();
             System.out.println(strFruitColor);
         }
         else if(field.isAnnotationPresent(FruitProvider.class)){
             FruitProvider fruitProvider= (FruitProvider) field.getAnnotation(FruitProvider.class);
             strFruitProvicer=" 供應商編號:"+fruitProvider.id()+" 供應商名稱:"+fruitProvider.name()+" 供應商地址:"+fruitProvider.address();
             System.out.println(strFruitProvicer);
         }
     }
    

    } } 按 Ctrl+C 復制代碼

Apple.java

按 Ctrl+C 復制代碼

import test.FruitColor.Color;

/**

  • 注解使用 */ public class Apple {

    @FruitName("Apple") private String appleName;

    @FruitColor(fruitColor=Color.RED) private String appleColor;

    @FruitProvider(id=1,name="陜西紅富士集團",address="陜西省西安市延安路89號紅富士大廈") private String appleProvider;

    public void setAppleColor(String appleColor) { this.appleColor = appleColor; } public String getAppleColor() { return appleColor; }

    public void setAppleName(String appleName) { this.appleName = appleName; } public String getAppleName() { return appleName; }

    public void setAppleProvider(String appleProvider) { this.appleProvider = appleProvider; } public String getAppleProvider() { return appleProvider; }

    public void displayName(){ System.out.println("水果的名字是:蘋果"); } } 按 Ctrl+C 復制代碼

FruitRun.java

按 Ctrl+C 復制代碼

/**

  • 輸出結果 */ public class FruitRun { public static void main(String[] args) { FruitInfoUtil.getFruitInfo(Apple.class); } } 按 Ctrl+C 復制代碼

運行結果是:

水果名稱:Apple 水果顏色:RED 供應商編號:1 供應商名稱:陜西紅富士集團 供應商地址:陜西省西安市延安路89號紅富士大廈

參考鏈接: [1] http://www.cnblogs.com/peida/archive/2013/04/26/3038503.html [2] http://www.cnblogs.com/whoislcj/p/5671622.html [3] http://blog.csdn.net/lylwo317/article/details/52163304


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

靖州| 博客| 原阳县| 内丘县| 桦甸市| 阿拉善盟| 曲沃县| 托克逊县| 阜康市| 偃师市| 交城县| 绵阳市| 浮梁县| 昂仁县| 孙吴县| 宁强县| 鲜城| 许昌市| 宝兴县| 平谷区| 政和县| 巴南区| 汾西县| 二连浩特市| 东宁县| 海林市| 莆田市| 通州市| 闽清县| 沁水县| 资阳市| 阿城市| 靖州| 永新县| 报价| 凤冈县| 焉耆| 隆安县| 文水县| 工布江达县| 治县。|