日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

Java注解原来如此通俗易懂

發(fā)布時(shí)間:2024/10/14 126 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java注解原来如此通俗易懂 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄:
1.注解概述
2.注解的作用分析
3.JDK中預(yù)定義的一些注解
4.自定義注解
5.元注解
6.解析注解

1.注解概述

Java注解是一系列元數(shù)據(jù),它提供數(shù)據(jù)用來(lái)解釋程序代碼,它是JDK1.5之后版本引入的新的特性,與類,接口,枚舉是同一個(gè)層次,它可以聲明在包,類,字段,方法,局部變量,方法參數(shù)等的前面,用來(lái)說(shuō)明程序的,注解并非是所解釋的代碼本身的一部分。注解對(duì)于代碼的運(yùn)行效果沒有直接影響

2.注解的作用分析

簡(jiǎn)單了解注解的作用:

注解作用:
1.編譯檢查:通過(guò)代碼里標(biāo)識(shí)的注解據(jù)讓編譯器實(shí)現(xiàn)基本的檢查
2.編寫文檔:通過(guò)代碼里標(biāo)識(shí)的注解生成文檔【doc文檔】
3.代碼分析:通過(guò)代碼標(biāo)識(shí)的注解對(duì)代碼進(jìn)行分析【使用反射】

1.編譯檢查
就比如我們接觸過(guò)的Override注解:
Override注解作用是檢查所注解方法是否重寫了父類的方法,如果不是注解的正確使用,編譯就不會(huì)通過(guò),這就是所謂的注解檢查:

2.編寫文檔
就是我們?cè)谖臋n注釋上加一點(diǎn)注解:

package annotation; /*** 計(jì)算兩數(shù)的和* @author itcat* @version 1.0* @since 1.5*/ public class AnnoDemo1 { /*** 計(jì)算兩數(shù)的和* @param a 整數(shù)* @param b 整數(shù)*/ public int add(int a,int b) {return a+b; } }

然后如果我們把上邊代碼編寫成文檔那么注解的內(nèi)容將會(huì)被翻譯成文檔中相應(yīng)的內(nèi)容
ps:博主不知道為啥不能生成文檔所以不能演示生成文檔后,文檔里邊的內(nèi)容,mmp這文檔肯定看不起我

當(dāng)然其實(shí)只要了解到它會(huì)在生成文檔中會(huì)被翻譯成對(duì)應(yīng)信息就行

3.代碼分析:通過(guò)代碼標(biāo)識(shí)的注解對(duì)代碼進(jìn)行分析【使用反射】,在下面詳細(xì)說(shuō)明

3.JDK預(yù)定義的注解

1.@Override:檢查被注解的方法是否是繼承自父類的
2.@Deprecated:將該注解標(biāo)注的內(nèi)容已經(jīng)過(guò)時(shí)
3.@Suppresswarnings:壓制警告

1.@Override:這個(gè)不多講,上邊的演示有
2.@Deprecated
例子:

我們可以看到當(dāng)我們選擇方法時(shí),show1上是有一個(gè)刪除線的,而show2是沒有的,這就是本注解的作用,雖然注解內(nèi)容已經(jīng)過(guò)時(shí)但是不影響我們對(duì)它的調(diào)用,java中標(biāo)注這個(gè)注解說(shuō)明該方法已經(jīng)存在更好的方法進(jìn)行替換

3.@Suppresswarnings
例子:

乍一看好像沒啥啊,但是可以把鼠標(biāo)放在紅色嘆號(hào)下邊的黃色橫杠上,就會(huì)出現(xiàn)提示信息,上圖就有一個(gè)Method 'show2()' is never used這個(gè)警告信息,如果不想要這些警告,那么就可以在你不想要的警告的方法上添加此注解,就會(huì)屏蔽。這個(gè)注解一般加在類上邊的部分,這樣就能屏蔽全部的警告

注意使用此注解一般需要加一個(gè)參數(shù)all,正確格式為@Suppresswarnings("all")

4.自定義注解

1.我們看一個(gè)系統(tǒng)自定義注解Override的注解格式分析:

@Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override { }

格式:

1.元注解:下邊會(huì)講
2.public @interface 注解名稱{}:一個(gè)類似于普通接口的接口,作用和使用規(guī)則和普通方法一樣

注解本質(zhì):

所有注解都會(huì)繼承得的公共接口,系統(tǒng)默認(rèn)為你繼承java.lang.annotation.Annotation接口

注解屬性:

就是注解的接口里邊可以定義的成員方法
要求:
1.屬性的返回值類型:
(1)基本數(shù)據(jù)類型
(2)String
(3)注解
(4)以上類型的數(shù)組
2.定義屬性后:
(1)使用時(shí)需要給屬性賦值
(2)如果定義屬性時(shí)使用default關(guān)鍵字給屬性默認(rèn)初始化值,則使用注解時(shí),可以不進(jìn)行屬性的賦值
(3)數(shù)組賦值的時(shí)候使用{}包裹,如果數(shù)組只有一個(gè)元素{}可以省略,如果只有一個(gè)屬性需要賦值,并且屬性的名稱是value那么賦值時(shí)value可以直接省略

為了方便理解舉個(gè)例子(對(duì)屬性返回值類型的要求):

很明顯void不合適(編譯不通過(guò)),注意我們把注解里邊的方法叫做屬性

接下來(lái)我們看看定義屬性后的對(duì)屬性進(jìn)行賦值的案例:

package annotation; public @interface AnnoDemo1 {int age();String str(); }@AnnoDemo1(age=12,str="張三") class person{int a;void fly(){System.out.println("我要飛的更高,摔的更慘");}public static void main(String[] args) {new person().fly();} }

很好奇是不是為啥方法會(huì)等于一個(gè)值,回答是java規(guī)定的,懂了嗎,你定義的方法必須要在使用的時(shí)候?yàn)榉椒ㄙx值,否則編譯不通過(guò)當(dāng)然不包括default

下面是對(duì)default和value這個(gè)特殊名稱的使用,str默認(rèn)值是李四,不使用默認(rèn)值的話就必須用注釋的部分進(jìn)行賦值:

package annotation; public @interface AnnoDemo1 {int value();String str() default "李四"; } @AnnoDemo1(12) //@AnnoDemo1(value = 12,str="王五") class person{int a;void fly(){System.out.println("我要飛的更高,摔的更慘");}public static void main(String[] args) {new person().fly();} }

當(dāng)我們賦一些特殊的值:

package annotation; public @interface AnnoDemo1 {MyEnum p();String[] str() ;Override over(); } @AnnoDemo1(p=MyEnum.p1,str={"123","234"},over = @Override) class person{int a;void fly(){System.out.println("我要飛的更高,摔的更慘");}public static void main(String[] args) {new person().fly();} }

附帶枚舉的代碼:

package annotation; public enum MyEnum {p1,p2; }

5.元注解

我們?cè)侔袿verride的源碼拿來(lái)分析:

@Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override { }

簡(jiǎn)單的說(shuō)元注解就是描述注解的注解,比如上邊的 @Target和@Retention

元注解是Java中定義好的注解,常用元注解:

注解名注解作用
@Target描述注解能夠作用的位置
@Retention描述注解被保留的階段
@Documented描述注解能否被抽取到api文檔中
@Inherited描述注解是否被子類繼承

1.@Target
源碼:

@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Target {/*** Returns an array of the kinds of elements an annotation type* can be applied to.* @return an array of the kinds of elements an annotation type* can be applied to*/ElementType[] value(); }

我們打開 ElementType源碼:

public enum ElementType {/** Class, interface (including annotation type), or enum declaration */TYPE,/** Field declaration (includes enum constants) */FIELD,/** Method declaration */METHOD,/** Formal parameter declaration */PARAMETER,/** Constructor declaration */CONSTRUCTOR,/** Local variable declaration */LOCAL_VARIABLE,/** Annotation type declaration */ANNOTATION_TYPE,/** Package declaration */PACKAGE,/*** Type parameter declaration** @since 1.8*/TYPE_PARAMETER,/*** Use of a type** @since 1.8*/TYPE_USE }

發(fā)現(xiàn)是一個(gè)枚舉類型的數(shù)據(jù),我們了解枚舉的三個(gè)取值:

(1)TYPE:可以作用于類上
(2)METHOD:可以作用于方法上
(3)FIELD:可以作用于成員變量上
ps:注意value可以省略不寫因?yàn)橹挥兴粋€(gè)需要賦值的


看到那個(gè)報(bào)錯(cuò)的小紅燈泡沒,就是因?yàn)槟阌盟揎椃椒?/strong>

2.@Retention
源碼:

@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Retention {/*** Returns the retention policy.* @return the retention policy*/RetentionPolicy value(); }

打開RetentionPolicy 源碼:

public enum RetentionPolicy {/*** Annotations are to be discarded by the compiler.*/SOURCE,/*** Annotations are to be recorded in the class file by the compiler* but need not be retained by the VM at run time. This is the default* behavior.*/CLASS,/*** Annotations are to be recorded in the class file by the compiler and* retained by the VM at run time, so they may be read reflectively.** @see java.lang.reflect.AnnotatedElement*/RUNTIME }

也是枚舉類型:

1.SOURCE:源碼階段
2. CLASS:類對(duì)象階段
3. RUNTIME:運(yùn)行時(shí)階段
一般參數(shù)是RUNTIME,意思是當(dāng)前被描述的注解會(huì)保留到class字節(jié)碼文件中,并被JVM讀取到
如果參數(shù)是CLASS意思是當(dāng)前被描述的注解會(huì)保留到class字節(jié)碼文件中,但不會(huì)被JVM讀取到
如果參數(shù)是SOURCE意思是當(dāng)前被描述的注解不會(huì)保留到class文件里

3.@Documented
就是描述此方法或其它的注解會(huì)被抽取到api文檔里邊:

畫紅線得到部分就是由于@Documented注解才使得劃線所代表注保留到了api文檔中

4.@Inherited
很好理解,如果父類的注解包含@Inherited那么子類即使不加注解也會(huì)默認(rèn)含有該注解

6.解析注解

那么什么是解析注解:即獲取注解中定義的屬性值

package untl2; import java.lang.reflect.Method; @pro(MethodName ="fly") public class MyReflect {public int a=12;public void fly(){System.out.println("我要飛的更高");}public static void main(String[] args) throws Exception {Class cls=MyReflect.class;//其實(shí)就是在內(nèi)存中生成了一個(gè)注解接口的子類實(shí)現(xiàn)類對(duì)象pro an=(pro) cls.getAnnotation(pro.class);String method=an.MethodName();Object obj=cls.newInstance();Method method1=cls.getMethod(method);method1.invoke(obj);} }運(yùn)行結(jié)果: 我要飛的更高

其實(shí)以上代碼等同:

package untl2; import java.lang.reflect.Method; @pro(MethodName ="fly") public class MyReflect {public int a=12;public void fly(){System.out.println("我要飛的更高");}public static void main(String[] args) throws Exception {Class cls=MyReflect.class;//其實(shí)就是在內(nèi)存中生成了一個(gè)注解接口的子類實(shí)現(xiàn)類對(duì)象Object obj=cls.newInstance();Method method1=cls.getMethod("fly");method1.invoke(obj);} } 運(yùn)行結(jié)果: 我要飛的更高

pro注解的定義代碼:

package untl2; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface pro {String MethodName(); }

getAnnotation是獲得注解的Class對(duì)象方法,然后就可以通過(guò).方法名拿到我們需要的注解里邊的屬性值。

一般來(lái)說(shuō)我們主要替換配置文件的時(shí)候用的注解比較多

總結(jié)

以上是生活随笔為你收集整理的Java注解原来如此通俗易懂的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。