java自定义注解类
一、前言
今天閱讀帆哥代碼的時(shí)候,看到了之前沒(méi)有見(jiàn)過(guò)的新東西, 比如java自定義注解類,如何獲取注解,如何反射內(nèi)部類,this$0是什么意思? 于是乎,學(xué)習(xí)并整理了一下。
二、代碼示例
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Field;//自定義注解類 @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface MyAnnotation {String name() default "hjzgg"; }public class Main {public Main(Class cls) {Field[] fields = cls.getDeclaredFields();TestAnnotation obj = null;try {obj = (TestAnnotation)cls.getConstructors()[0].newInstance(this);//獲取內(nèi)部類對(duì)象} catch (Exception e) {e.printStackTrace();}for(Field field : fields) {System.out.println(field.getName() + " " + field.getType().getName());if(!field.getName().equals("this$0")) { MyAnnotation annotation = field.getAnnotation(MyAnnotation.class);//獲取注解類String name = annotation.name();field.setAccessible(true);try {switch(name) {case "hjzgg":switch(field.getType().getName()) {case "int":case "java.lang.Integer":field.set(obj, 555);break;case "java.lang.String":field.set(obj, "hehe");break;}break;case "lxkdd":switch(field.getType().getName()) {case "int":case "java.lang.Integer":field.set(obj, 555);break;case "java.lang.String":field.set(obj, "hehe");break;}break;default:break;}} catch (Exception e) {e.printStackTrace();}}}System.out.println(obj);}public static void main(String[] args) throws InstantiationException, IllegalAccessException {new Main(TestAnnotation.class);}class TestAnnotation{public TestAnnotation(){}@MyAnnotation(name="lxkdd")private int x;@MyAnnotationprivate String y;public int getX() {return x;}public void setX(int x) {this.x = x;}public String getY() {return y;}public void setY(String y) {this.y = y;}@Overridepublic String toString() {return "x: " + x + ", y: " + y; }} }
三、代碼分析
1.如何編寫(xiě)自定義注解
public @interface MyAnnotation { String value() default "hahaha"; }感覺(jué)等價(jià)于
public class MyAnnotation extends java.lang.annotation.Annotation{ private String value = "hahaha"; public void setValue(String value){ this.value = value; } public String getValue(){ return value; } }自定義注解類規(guī)則
@interface實(shí)際上是繼承了java.lang.annotation.Annotation,所以定義annotation時(shí)不能繼承其他annotation或interface.?java.lang.annotation.Retention告訴編譯器如何對(duì)待 Annotation,使用Retention時(shí),需要提供java.lang.annotation.RetentionPolicy的枚舉值.
public enum RetentionPolicy { SOURCE, // 編譯器處理完Annotation后不存儲(chǔ)在class中 CLASS, // 編譯器把Annotation存儲(chǔ)在class中,這是默認(rèn)值 RUNTIME // 編譯器把Annotation存儲(chǔ)在class中,可以由虛擬機(jī)讀取,反射需要 }? java.lang.annotation.Target告訴編譯器Annotation使用在哪些地方,使用需要指定java.lang.annotation.ElementType的枚舉值.
public enum ElementType { TYPE, // 指定適用點(diǎn)為 class, interface, enum FIELD, // 指定適用點(diǎn)為 field METHOD, // 指定適用點(diǎn)為 method PARAMETER, // 指定適用點(diǎn)為 method 的 parameter CONSTRUCTOR, // 指定適用點(diǎn)為 constructor LOCAL_VARIABLE, // 指定使用點(diǎn)為 局部變量 ANNOTATION_TYPE, //指定適用點(diǎn)為 annotation 類型 PACKAGE // 指定適用點(diǎn)為 package }? ?java.lang.annotation.Documented用于指定該Annotation是否可以寫(xiě)入javadoc中.?
? ?java.lang.annotation.Inherited用于指定該Annotation用于父類時(shí)是否能夠被子類繼承.?
示例
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Documented //這個(gè)Annotation可以被寫(xiě)入javadoc @Inherited //這個(gè)Annotation 可以被繼承 @Target({ElementType.CONSTRUCTOR,ElementType.METHOD}) //表示這個(gè)Annotation只能用于注釋 構(gòu)造子和方法 @Retention(RetentionPolicy.CLASS) //表示這個(gè)Annotation存入class但vm不讀取 public @interface MyAnnotation { String value() default "hahaha"; }2.如何獲取自定義注解
??java.lang.reflect.AnnotatedElement接口提供了四個(gè)方法來(lái)訪問(wèn)Annotation
public Annotation getAnnotation(Class annotationType); public Annotation[] getAnnotations(); public Annotation[] getDeclaredAnnotations(); public boolean isAnnotationPresent(Class annotationType);?來(lái)自:http://blog.csdn.net/foamflower/article/details/5946451
? ?Class、Constructor、Field、Method、Package等都實(shí)現(xiàn)了該接口,可以通過(guò)這些方法訪問(wèn)Annotation信息,前提是要訪問(wèn)的Annotation指定Retention為RUNTIME.?
? ? ?Java內(nèi)置的annotation有Override Deprecated SuppressWarnings.?
? ? ?Override只用于方法,它指明注釋的方法重寫(xiě)父類的方法,如果不是,則編譯器報(bào)錯(cuò).?
? ? ?Deprecated指明該方法不建議使用.
? ? ?SuppressWarnings告訴編譯器:我知道我的代碼沒(méi)問(wèn)題.
3.this$0是什么意思?
public class Outer {//this$0 public class FirstInner {//this$1 public class SecondInner {//this$2 public class ThirdInner { } } }}
說(shuō)一個(gè)場(chǎng)景:當(dāng)我們拿到了一個(gè)內(nèi)部類的對(duì)象Inner,但是又想獲取其對(duì)應(yīng)的外部類Outer,那么就可以通過(guò)this$0來(lái)獲取。this$0就是內(nèi)部類所自動(dòng)保留的一個(gè)指向所在外部類的引用。?
//通過(guò)工具獲取到Inner實(shí)例對(duì)象 Outer.Inner inner = getInner(); //獲取內(nèi)部類Inner的一個(gè)字段this$0信息 //this$0特指該內(nèi)部類所在的外部類的引用,不需要手動(dòng)定義,編譯時(shí)自動(dòng)加上 Filed outerField = inner.getClass().getDeclaredField("this$0"); //this$0是私有的,提升訪問(wèn)權(quán)限 outerField.setAccessible(true); //拿到該字段上的實(shí)例值 Outer outer = (Outer)outerField.get(inner);4.java如何反射內(nèi)部類
Class<?> cls = Class.forName("package.OuterClass$InnerClass"); or Class<?> cls = OuterClass.InnerClass.class; (1)OuterClass.InnerClass obj = (OuterClass.InnerClass)cls.getConstructors()[0].newInstance(new OuterClass());(2)OuterClass.InnerClass obj = (OuterClass.InnerClass)cls.getConstructor(OuterClass.class).newInstance(new OuterClass());
由此可見(jiàn),內(nèi)部類的無(wú)參構(gòu)造器在通過(guò)反射機(jī)制獲取時(shí),要指定其父類參數(shù)才可以獲得,否則將報(bào)如下異常:
java.lang.NoSuchMethodException: com.hjzgg.OuterClass$InnerClass.<init>()at java.lang.Class.getConstructor0(Class.java:3082)at java.lang.Class.getConstructor(Class.java:1825)?
轉(zhuǎn)載于:https://www.cnblogs.com/hujunzheng/p/5719611.html
總結(jié)
以上是生活随笔為你收集整理的java自定义注解类的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 魅族18拍照怎么样 不凑数三摄镜组亮点功
- 下一篇: 如何计算徽商银行信用卡年费 收费标准和规