电竞比分网-中国电竞赛事及体育赛事平台

分享

淺談———Java注解詳解

 諤諤熱 2017-08-12

有些同學(xué)向我反映,Java注解老是整不明白,那么筆者就專門寫篇文章來帶同學(xué)們學(xué)習(xí)學(xué)習(xí),順便筆者也復(fù)習(xí)一下。

Java注解詳解

Java中的注解可不是注釋,注意區(qū)別。Java注解是跟編譯器直接掛鉤,在JDK1.5之后就出現(xiàn)了注解,那么注解究竟是干嘛的呢?開發(fā)者把它開發(fā)出來是為了干什么的呢?

1.生成文檔。這是最常見的,也是java最早提供的注解。常用的有@see@param@return等,這點都很熟悉,不就是生成自己的API嘛。

2.跟蹤代碼依賴性,實現(xiàn)替代配置文件功能。比較常見的是spring2.5開始的基于注解配置。作用就是減少配置?,F(xiàn)在的框架基本都使用了這種配置來減少配置文件的數(shù)量。

3.在編譯時進(jìn)行格式檢查。如@Override放在方法前,如果你這個方法并不是覆蓋了超類方法,則編譯時就能檢查出。

所以要想成為一名優(yōu)秀的Java開發(fā)程序員,注解的掌握那是必須的。

1.Java中自帶的注解

@Override

子類對父類方法的重寫所帶的注解,這個筆者就不多說啦!簡單

@Deprecated

表示已經(jīng)過時,不建議使用,但是依然可以使用

比如你在調(diào)用Thread類的stop方法的時候出現(xiàn)一條橫杠,這就是加了@Deprecated的效果,我截個圖給你看看:

這條杠是編譯器告訴你此方法已經(jīng)過時啦,所以加條杠提示你一下,但是依然可以調(diào)用,并不是不能使用,而是建議不要使用。

@SuppressWarnings

用來抑制編譯時的警告信息,編譯器在你寫代碼的時候,難免會出現(xiàn)很多的警告,有強(qiáng)迫癥的程序猿會感到極其不爽,那么腫么辦呢?@SuppressWarnings注解就可以告訴編譯器,別警告啦,代碼不會有問題的。

比如你想把調(diào)用Thread的stop方法的警告去掉,那么你就可以這么寫:

有的同學(xué)可能不理解@SuppressWarnings(“all”)中的”all”是啥意思?其實很簡單,@SuppressWarnings注解一定要傳遞一個參數(shù)給它,來表示過濾掉哪些類型的警告,筆者添加了”all”表示過濾掉所有類型的警告,很好理解吧!那么還可以傳遞什么參數(shù)來過濾警告呢?看看下面的表格你就會知道啦:

還有一些其它的Java自帶注解,筆者就不一一說明了。

2.自定義注解

在學(xué)會自定義注解之前,我們必須先來理解一下Java當(dāng)中用來給自定義注解而注解的元注解,有點繞口哈!沒關(guān)系,其實很簡單,就是說你要自定義一個注解,你必須說明一下這個自定義的注解的使用范圍以及保存注解信息,還有是否包含于Javadoc中,是否允許子類繼承父類中的注解。這4點分別對應(yīng)這4種元注解,看下面的表格你就懂啦:

Java4種元注解表格

自定義注解使用關(guān)鍵字@interface,這跟接口有點像,只不過一個”@”符號的差別,還有就是Java注解不支持繼承,示例代碼如下:

@Target(value={ElementType.METHOD})//這里表示此注解只能被使用于方法

@Retention(RetentionPolicy.RUNTIME)//通常默認(rèn)使用RUNTIME

@Documented

@Inherited

public@interfaceMyAnnotation{

/*注意在注解當(dāng)中屬性聲明是:

*類型+屬性名;

*不是聲明一個方法,這一定要區(qū)別開來

*/

Stringstr;//注解的屬性聲明,屬性類型為String,名字是'str'

}

參考元注解表格,使用”@interface”關(guān)鍵字聲明,注意屬性的聲明末尾是有””的。還有一點就是注解的元素(屬性)只支持:

1.所有的基本類型

2.String

3.Class

4.enum

5.Annotation

6.String,Class,enum,Annotation以及基本類型數(shù)組

其他的類型都會報錯

學(xué)會聲明了,那么如何使用這個注解呢?示例代碼如下:

//@MyAnnotation(str='王者榮耀')用在聲明類這里是報錯的,因為筆者的注解@MyAnnotation只能用于方法

publicclassStudent{

publicStringname;

publicintage;

@MyAnnotation(str='王者榮耀')//用在這里不會報錯

publicvoidplayAndroidGame{

System.out.println(this.name+'玩王者榮耀!');

}

}

目前的注解好像用途并沒有完全體現(xiàn)出來,因為你沒有為注解添加注解處理器,沒有添加注解處理器的注解跟注釋沒任何區(qū)別,所以我們必須為注解添加一個注解處理器,才能讓注解的真正用途體現(xiàn)出來,這需要反射的知識,如果你對反射不熟,那么注解處理器怕是有些困難。

3.通過反射創(chuàng)建和使用注解器

講解注解器需要一個實例作為參考,我們來設(shè)計這么一個注解器,可以通過注解器來獲取某個類的所有信息。一個類里面會存在屬性,方法,內(nèi)部類,構(gòu)造函數(shù)等,那么我們?nèi)绾瓮ㄟ^注解的方式去獲取到一個類的所有信息呢?首先來設(shè)計我們的注解:

類的注解:元素(屬性)僅包含類名

@Target(value=ElementType.TYPE)//使用范圍類,接口,enum等

//要想通過反射獲取這個注解信息,此注解一定要保留于運行期,所以這里@@Retention必須是RUNTIME的

@Retention(RetentionPolicy.RUNTIME)

public@interfaceClassAnnotation{

StringclassName;//類的名字

}

類的屬性的注解:元素(屬性)包含–>屬性名,訪問權(quán)限,屬性類型

@Target(value=ElementType.FIELD)//使用于類的成員屬性

@Retention(RetentionPolicy.RUNTIME)

public@interfaceFieldAnnotation{

StringfieldName;//屬性的名字

StringaccessPer;//訪問權(quán)限

StringfieldType;//屬性的類型

}

方法的注解:元素(屬性)包含–>方法名,參數(shù)列表,返回值類型,訪問權(quán)限,方法的功能

@Target(value=ElementType.METHOD)//使用于方法

@Retention(RetentionPolicy.RUNTIME)

public@interfaceMethodAnnotation{

StringmethodName;//方法的名字

ClassparameterList;//參數(shù)列表

StringreturnType;//返回值類型

StringaccessPer;//訪問權(quán)限

StringmethodFunction;//方法的功能描述

}

構(gòu)造器的注解:元素(屬性)包含–>構(gòu)造器的名名,參數(shù)列表,返回值類型,訪問權(quán)限

@Target(value=ElementType.CONSTRUCTOR)//使用于構(gòu)造器

@Retention(RetentionPolicy.RUNTIME)

public@interfaceConstructorAnnotation{

StringconName;//構(gòu)造器的名字

ClassparameterList;//參數(shù)列表

ClassreturnType;//返回值類型

StringaccessPer;//訪問權(quán)限

}

注解已經(jīng)定義完成,下面一步就是將注解應(yīng)用于一個類當(dāng)中,示例代碼如下:

importDate20170810.Annotation.ClassAnnotation;

importDate20170810.Annotation.ConstructorAnnotation;

importDate20170810.Annotation.FieldAnnotation;

importDate20170810.Annotation.MethodAnnotation;

@ClassAnnotation(className='Studnet')

publicclassStudent{

@FieldAnnotation(fieldName='name',accessPer='private',fieldType='String')

privateStringname='';

@FieldAnnotation(fieldName='age',accessPer='private',fieldType='int')

privateintage=0;

@ConstructorAnnotation(methodName='Studnet',parameterList={String.class,int.class},

returnType=Student.class,accessPer='public')

publicStudent(Stringname,intage){

this.age=age;

this.name=name;

}

@MethodAnnotation(methodName='getName',parameterList={},returnType=String.class,

accessPer='public',methodFunction='返回當(dāng)前Student實例對象的名字name')

publicStringgetName{

returnthis.name;

}

@MethodAnnotation(methodName='setName',parameterList={String.class},returnType=Void.class,

accessPer='public',methodFunction='設(shè)置當(dāng)前Student實例對象的名字name')

publicvoidsetName(Stringname){

this.name=name;

}

@MethodAnnotation(methodName='getAge',parameterList={},returnType=int.class,

accessPer='public',methodFunction='返回當(dāng)前Student實例對象的年齡age')

publicintgetAge{

returnthis.age;

}

@MethodAnnotation(methodName='setAge',parameterList={int.class},returnType=Void.class,

accessPer='public',methodFunction='設(shè)置當(dāng)前Student實例對象的年齡age')

publicvoidsetAge(intage){

this.age=age;

}

@MethodAnnotation(methodName='playAndroidGame',parameterList={},returnType=Void.class,

accessPer='public',methodFunction='王者榮耀有關(guān),就是對小學(xué)生玩王者榮耀太厲害的吐槽!')

publicvoidplayAndroidGame{

System.out.println('hello,I'm'+this.name+',今年'+this.age+'歲啦');

if(this.age>12){

System.out.println(this.age+'歲,打王者榮耀還可以不算太坑!');

}else{

System.out.println('由于是小學(xué)生,王者排位就算啦,不如來一盤匹配,'+

'排位萬萬不可!因為啥?怕排位的時候小學(xué)生說我辣雞!');

}

}

}

下面就是通過反射來獲取Student類的所有信息啦!示例代碼如下:

//注解器

publicclassAnnotatorDemo{

//通過反射獲取類的注解信息

publicstaticvoidgetClassAnnotationMessage(Classclass1){

System.out.println('類的注解信息:');

for(java.lang.annotation.Annotationannotation:class1.getDeclaredAnnotations){

System.out.println(annotation);

//獲取類注解屬性className的值

if(annotation.annotationType.equals(ClassAnnotation.class)){

StringclassName=((ClassAnnotation)annotation).className;

System.out.println('類名:'+className);

}

}

}

//通過反射獲取屬性的注解信息

publicstaticvoidgetFieldAnnotationMessage(Classclass1){

System.out.println('屬性注解的信息:');

Fieldfields=class1.getDeclaredFields;

for(Fieldfield:fields){

System.out.println;

FieldAnnotationfieldAnnotation=field.getDeclaredAnnotation(FieldAnnotation.class);

System.out.println(fieldAnnotation);

//獲取屬性注解的各種值

StringfieldName=fieldAnnotation.fieldName;

System.out.println('屬性名:'+fieldName);

StringaccessPer=fieldAnnotation.accessPer;

System.out.println('屬性訪問權(quán)限:'+accessPer);

ClassfieldType=fieldAnnotation.fieldType;

System.out.println('屬性的類型:'+fieldType);

}

}

//獲取構(gòu)造器的注解信息

publicstaticvoidgetConstrutorAnnotationMessage(Classclass1){

System.out.println('構(gòu)造器注解的信息:');

Constructorconstructors=class1.getDeclaredConstructors;

for(Constructorconstructor:constructors){

System.out.println;

ConstructorAnnotationconstructorAnnotation=constructor.getDeclaredAnnotation(ConstructorAnnotation.class);

System.out.println(constructorAnnotation);

StringconName=constructorAnnotation.conName;

System.out.println('構(gòu)造器的名字:'+conName);

System.out.print('構(gòu)造器的參數(shù)列表:');

ClassparameterList=constructorAnnotation.parameterList;

for(Classc:parameterList){

System.out.print('['+c.getName+']');

}

System.out.println;

ClassreturnType=constructorAnnotation.returnType;

System.out.println('返回值類型:'+returnType.getName);

StringaccessPer=constructorAnnotation.accessPer;

System.out.println('訪問權(quán)限:'+accessPer);

}

}

publicstaticvoidgetMethodAnnotationMessage(Classclass1){

System.out.println('方法注解的信息:');

Methodmethods=class1.getDeclaredMethods;

for(Methodmethod:methods){

System.out.println;

MethodAnnotationmethodAnnotation=method.getDeclaredAnnotation(MethodAnnotation.class);

System.out.println(methodAnnotation);

StringmethodName=methodAnnotation.methodName;

System.out.println('方法的名字:'+methodName);

ClassparameterList=methodAnnotation.parameterList;

System.out.print('方法參數(shù)參數(shù)列表:');

//判斷參數(shù)列表是否個數(shù)為0

if(parameterList.length==0){

//說明此方法無參

System.out.println('無參');

}else{

//說明此方法有參

for(Classc:parameterList){

System.out.print('['+c.getName+']');

}

System.out.println;

}

ClassreturnType=methodAnnotation.returnType;

System.out.println('方法的返回值類型:'+returnType.getName);

StringaccessPer=methodAnnotation.accessPer;

System.out.println('方法的訪問權(quán)限:'+accessPer);

StringmethodFunction=methodAnnotation.methodFunction;

System.out.println('方法的功能描述:'+methodFunction);

}

}

publicstaticvoidmain(Stringargs){

Classclass_Student=Student.class;

//得到類注解的信息

getClassAnnotationMessage(class_Student);

System.out.println('\n');

//得到屬性注解的信息

getFieldAnnotationMessage(class_Student);

System.out.println('\n');

//得到構(gòu)造器的注解的信息

getConstrutorAnnotationMessage(class_Student);

System.out.println('\n');

//得到方法的注解的信息

getMethodAnnotationMessage(class_Student);

}

運行結(jié)果:

類的注解信息:

@Date20170810.Annotation.ClassAnnotation(className=Student)

類名:Student

屬性注解的信息:

@Date20170810.Annotation.FieldAnnotation(fieldName=name,accessPer=private,fieldType=classjava.lang.String)

屬性名:name

屬性訪問權(quán)限:private

屬性的類型:classjava.lang.String

@Date20170810.Annotation.FieldAnnotation(fieldName=age,accessPer=private,fieldType=int)

屬性名:age

屬性訪問權(quán)限:private

屬性的類型:int

構(gòu)造器注解的信息:

@Date20170810.Annotation.ConstructorAnnotation(conName=Studnet,parameterList=[classjava.lang.String,int],returnType=classDate20170810.Student,accessPer=public)

構(gòu)造器的名字:Studnet

構(gòu)造器的參數(shù)列表:[java.lang.String][int]

返回值類型:Date20170810.Student

訪問權(quán)限:public

方法注解的信息:

@Date20170810.Annotation.MethodAnnotation(methodName=getName,parameterList=,returnType=classjava.lang.String,accessPer=public,methodFunction=返回當(dāng)前Student實例對象的名字name)

方法的名字:getName

方法參數(shù)參數(shù)列表:無參

方法的返回值類型:java.lang.String

方法的訪問權(quán)限:public

方法的功能描述:返回當(dāng)前Student實例對象的名字name

@Date20170810.Annotation.MethodAnnotation(methodName=setName,parameterList=[classjava.lang.String],returnType=classjava.lang.Void,accessPer=public,methodFunction=設(shè)置當(dāng)前Student實例對象的名字name)

方法的名字:setName

方法參數(shù)參數(shù)列表:[java.lang.String]

方法的返回值類型:java.lang.Void

方法的訪問權(quán)限:public

方法的功能描述:設(shè)置當(dāng)前Student實例對象的名字name

@Date20170810.Annotation.MethodAnnotation(methodName=setAge,parameterList=[int],returnType=classjava.lang.Void,accessPer=public,methodFunction=設(shè)置當(dāng)前Student實例對象的年齡age)

方法的名字:setAge

方法參數(shù)參數(shù)列表:[int]

方法的返回值類型:java.lang.Void

方法的訪問權(quán)限:public

方法的功能描述:設(shè)置當(dāng)前Student實例對象的年齡age

@Date20170810.Annotation.MethodAnnotation(methodName=playAndroidGame,parameterList=,returnType=classjava.lang.Void,accessPer=public,methodFunction=王者榮耀有關(guān),就是對小學(xué)生玩王者榮耀太厲害的吐槽!)

方法的名字:playAndroidGame

方法參數(shù)參數(shù)列表:無參

方法的返回值類型:java.lang.Void

方法的訪問權(quán)限:public

方法的功能描述:王者榮耀有關(guān),就是對小學(xué)生玩王者榮耀太厲害的吐槽!

@Date20170810.Annotation.MethodAnnotation(methodName=getAge,parameterList=,returnType=int,accessPer=public,methodFunction=返回當(dāng)前Student實例對象的年齡age)

方法的名字:getAge

方法參數(shù)參數(shù)列表:無參

方法的返回值類型:int

方法的訪問權(quán)限:public

方法的功能描述:返回當(dāng)前Student實例對象的年齡age

一定要自己完成一遍…….

搞明白了這個例子,那么你對注解的掌握就完成了一大半,為什么筆者不寫其他牛的例子,而只寫如何使用注解獲取類的所有信息的例子,因為你只要通過注解獲取到類的所有信息,那么很多框架,包括自己想寫框架,在你一次次寫注解的時候,你就慢慢掌握啦!

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多