自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

掌握 Java 注解,一夜陸地神仙

開(kāi)發(fā) 后端
元數(shù)據(jù)是指用來(lái)描述數(shù)據(jù)的數(shù)據(jù),通俗一點(diǎn),就是描述代碼間關(guān)系,或者代碼與其它資源(例如數(shù)據(jù)庫(kù)表)之間內(nèi)在聯(lián)系的數(shù)據(jù)。

一、注解簡(jiǎn)介

Java注解用于為Java代碼提供元數(shù)據(jù)。

元數(shù)據(jù)是指用來(lái)描述數(shù)據(jù)的數(shù)據(jù),通俗一點(diǎn),就是描述代碼間關(guān)系,或者代碼與其它資源(例如數(shù)據(jù)庫(kù)表)之間內(nèi)在聯(lián)系的數(shù)據(jù)。在一些技術(shù)框架中,如Struts、hibernate就不知不覺(jué)用到了元數(shù)據(jù)。對(duì)于Struts來(lái)說(shuō),元數(shù)據(jù)指的是struts-config.xml;對(duì)hibernate來(lái)說(shuō)就是hbm文件。以上闡述的幾種元數(shù)據(jù)都是基于xml文件的或者其他形式的單獨(dú)配置文件。這樣表示有些不便之處。1、與被描述的文件分離,不利于一致性的維護(hù);2、所有這樣的文件都是ASCII文件,沒(méi)有顯式的類型支持。基于元數(shù)據(jù)的廣泛使用,JDK5.0引入了Annotation的概念來(lái)描述元數(shù)據(jù)。在Java中,元數(shù)據(jù)以標(biāo)簽的形式存在于Java代碼中,元數(shù)據(jù)標(biāo)簽的存在并不影響程序代碼的編譯和執(zhí)行。簡(jiǎn)而言之,言而總之,注解就是標(biāo)簽的意思。

二、如何創(chuàng)建注解

JDK5.0出來(lái)后,Java語(yǔ)言中就有了四種類型,即類class、枚舉enum、接口interface、注解@interface,它們處于同一級(jí)別,Java就是通過(guò)注解來(lái)表示元數(shù)據(jù)的。

  1. package com.guor.ClientNew; 
  2.   
  3. public @interface MyAnnotation { 
  4.     // 定義公共的final靜態(tài)屬性 
  5.     int age = 25; 
  6.   
  7.     // 定義公共的抽象方法 
  8.     String name(); 

Java注解本質(zhì)上就是接口,是繼承了Annotation接口的接口。

三、元注解

元注解是可以注解到注解上的注解,或者說(shuō)元注解是一種基本注解,它能夠應(yīng)用到其它的注解上面。

元標(biāo)簽有 @Retention、@Documented、@Target、@Inherited、@Repeatable 5 種。

1、@Retention

Retention,中文釋義保留期的意思

當(dāng)@Retention應(yīng)用到注解上的時(shí)候,它解釋說(shuō)明了這個(gè)注解的生命周期。

  • RetentionPolicy.SOURCE 注解只在源碼階段保留,在編譯器進(jìn)行編譯時(shí)它將被丟棄忽視。
  • RetentionPolicy.CLASS 注解只被保留到編譯進(jìn)行的時(shí)候,它并不會(huì)被加載到JVM中。
  • RetentionPolicy.RUNTIME 注解可以保留到程序運(yùn)行的時(shí)候,它會(huì)被加載到JVM中。

2、@Documented

顧名思義,這個(gè)元注解肯定和文檔有關(guān)。它的作用是能夠?qū)⒆⒔庵械脑匕絁avadoc中去。

3、@Target

標(biāo)明注解運(yùn)用的地方。

  • ElementType.ANNOTATION_TYPE 可以給一個(gè)注解進(jìn)行注解
  • ElementType.CONSTRUCTOR 可以給構(gòu)造方法進(jìn)行注解
  • ElementType.FIELD 可以給屬性進(jìn)行注解
  • ElementType.LOCAL_VARIABLE 可以給局部變量進(jìn)行注解
  • ElementType.METHOD 可以給方法進(jìn)行注解
  • ElementType.PACKAGE 可以給一個(gè)包進(jìn)行注解
  • ElementType.PARAMETER 可以給一個(gè)方法內(nèi)的參數(shù)進(jìn)行注解
  • ElementType.TYPE 可以給一個(gè)類型進(jìn)行注解,比如類、接口、枚舉

4、@Inherited

lnherited是繼承的意思。

如果一個(gè)超類被@Inherited注解過(guò)的注解進(jìn)行注解的話,那么如果它的子類沒(méi)有被任何注解應(yīng)用的話,那么這個(gè)子類就繼承了超類的注解。

代碼實(shí)例

5、@Repeatable

Repeatable 自然是可重復(fù)的意思。@Repeatable 是 Java 1.8 才加進(jìn)來(lái)的,所以算是一個(gè)新的特性。

什么樣的注解會(huì)多次應(yīng)用呢?通常是注解的值可以同時(shí)取多個(gè)。

在生活中一個(gè)人往往是具有多種身份,如果我把每種身份當(dāng)成一種注解該如何使用???

先聲明一個(gè)Persons類用來(lái)包含所有的身份

  1. @Target(ElementType.TYPE)   
  2. @Retention(RetentionPolicy.RUNTIME) 
  3. public @interface Persons { 
  4.   Person[] value(); 

這里@Target是聲明Persons注解的作用范圍,參數(shù)ElementType.Type代表可以給一個(gè)類型進(jìn)行注解,比如類,接口,枚舉。

@Retention是注解的有效時(shí)間,RetentionPolicy.RUNTIME是指程序運(yùn)行的時(shí)候。

Person注解:

  1. @Repeatable(Persons.class) 
  2. public @interface Person{ 
  3.   String role() default ""

@Repeatable括號(hào)內(nèi)的就相當(dāng)于用來(lái)保存該注解內(nèi)容的容器。

聲明一個(gè)Man類,給該類加上一些身份。

  1. @Person(role="CEO"
  2. @Person(role="husband"
  3. @Person(role="father"
  4. @Person(role="son"
  5. public class Man { 
  6.   String name=""

在主方法中訪問(wèn)該注解:

  1. public static void main(String[] args) { 
  2.     Annotation[] annotations = Man.class.getAnnotations();   
  3.     System.out.println(annotations.length); 
  4.     Persons p1=(Persons) annotations[0]; 
  5.     for(Person t:p1.value()){ 
  6.         System.out.println(t.role()); 
  7.     } 

下面的代碼結(jié)果輸出相同,但是可以先判斷是否是相應(yīng)的注解,比較嚴(yán)謹(jǐn)。

  1. if(Man.class.isAnnotationPresent(Persons.class)) { 
  2.     Persons p2=Man.class.getAnnotation(Persons.class); 
  3.     for(Person t:p2.value()){ 
  4.         System.out.println(t.role()); 
  5.     } 
  6.  } 

運(yùn)行結(jié)果:

四、注解的屬性

注解的屬性也叫做成員變量,注解只有成員變量,沒(méi)有方法。注解的成員變量在注解的定義中以“無(wú)參的方法”形式來(lái)聲明,其方法名定義了該成員變量的名字,其返回值定義了該成員變量的類型。

  1. @Target(ElementType.TYPE) 
  2. @Retention(RetentionPolicy.RUNTIME) 
  3. public @interface TestAnnotation { 
  4.     int id(); 
  5.     String msg(); 

上面代碼中定義了TestAnnotation這個(gè)注解中擁有id和msg兩個(gè)屬性。在使用的時(shí)候,我們應(yīng)該給他們進(jìn)行賦值。

賦值的方式是在注解的括號(hào)內(nèi)以value=“”形式,多個(gè)屬性之前用,隔開(kāi)。

  1. @TestAnnotation(id=3,msg="hello annotation"
  2. public class Test { 

需要注意的是,在注解中定義屬性時(shí)它的類型必須是 8 種基本數(shù)據(jù)類型外加 類、接口、注解及它們的數(shù)組。

注解中屬性可以有默認(rèn)值,默認(rèn)值需要用 default 關(guān)鍵值指定。比如:

  1. @Target(ElementType.TYPE) 
  2. @Retention(RetentionPolicy.RUNTIME) 
  3. public @interface TestAnnotation { 
  4.     public int id() default -1; 
  5.     public String msg() default "哪吒"

TestAnnotation 中 id 屬性默認(rèn)值為 -1,msg 屬性默認(rèn)值為 哪吒。

它可以這樣應(yīng)用。

  1. @TestAnnotation() 
  2. public class Test {} 

因?yàn)橛心J(rèn)值,所以無(wú)需要再在 @TestAnnotation 后面的括號(hào)里面進(jìn)行賦值了,這一步可以省略。

另外,還有一種情況。如果一個(gè)注解內(nèi)僅僅只有一個(gè)名字為 value 的屬性時(shí),應(yīng)用這個(gè)注解時(shí)可以直接將屬性值填寫(xiě)到括號(hào)內(nèi)。

  1. public @interface Check { 
  2.     String value(); 

上面代碼中,Check 這個(gè)注解只有 value 這個(gè)屬性。所以可以這樣應(yīng)用。

  1. @Check("hi"
  2. int a; 

這和下面的效果是一樣的

  1. @Check(value="hi"
  2. int a; 

最后,還需要注意的一種情況是一個(gè)注解沒(méi)有任何屬性。比如:

  1. public @interface Perform {} 

那么在應(yīng)用這個(gè)注解的時(shí)候,括號(hào)都可以省略。

  1. @Perform 
  2. public void testMethod(){} 

五、Java自帶的注解

學(xué)習(xí)了上面相關(guān)的知識(shí),我們已經(jīng)可以自己定義一個(gè)注解了。其實(shí) Java 語(yǔ)言本身已經(jīng)提供了幾個(gè)現(xiàn)成的注解。

1、@Override

這個(gè)大家應(yīng)該很熟悉了,提示子類要復(fù)寫(xiě)父類中被 @Override 修飾的方法

2、@Deprecated

加上這個(gè)注解之后,表示此方法或類不再建議使用,調(diào)用時(shí)會(huì)出現(xiàn)刪除線,但不代表不能用,只是說(shuō),不推薦使用,因?yàn)橛懈玫姆椒梢哉{(diào)用。

那么直接刪掉不就完了?

因?yàn)樵谝粋€(gè)項(xiàng)目中,工程比較大,代碼比較多,而在后續(xù)的開(kāi)發(fā)過(guò)程中,可能之前的某個(gè)方法實(shí)現(xiàn)的并不是很合理,這個(gè)時(shí)候要重新寫(xiě)一個(gè)方法,而之前的方法還不能隨便刪,因?yàn)閯e的地方可能在調(diào)用它,所以加上這個(gè)注解,就OK啦!

3、@SuppressWarning

阻止警告的意思。

該批注的作用是給編譯器一條指令,告訴它對(duì)被批注的代碼元素內(nèi)部的某些警告保持靜默。

4、@SafeVarargs

參數(shù)安全類型注解。

它的目的是提醒開(kāi)發(fā)者不要用參數(shù)做一些不安全的操作,它的存在會(huì)阻止編譯器產(chǎn)生unchecked這樣的警告。

在聲明具有模糊類型(比如:泛型)的可變參數(shù)的構(gòu)造函數(shù)或方法時(shí),Java編譯器會(huì)報(bào)unchecked警告。鑒于這種情況,如果程序猿斷定聲明的構(gòu)造函數(shù)和方法的主體no problem,可使用@SafeVarargs進(jìn)行標(biāo)記,這樣Java編譯器就不會(huì)報(bào)unchecked警告了!

5、@FunctionalInterface

Java 8為函數(shù)式接口引入了一個(gè)新注解@FunctionalInterface,主要用于編譯級(jí)錯(cuò)誤檢查,加上該注解,當(dāng)你寫(xiě)的接口不符合函數(shù)式接口定義的時(shí)候,編譯器會(huì)報(bào)錯(cuò)。

它們主要用在Lambda表達(dá)式和方法引用(實(shí)際上也可認(rèn)為是Lambda表達(dá)式)上。

如定義了一個(gè)函數(shù)式接口如下:

  1. @FunctionalInterface 
  2. interface GreetingService  
  3.     void sayMessage(String message); 

那么就可以使用Lambda表達(dá)式來(lái)表示該接口的一個(gè)實(shí)現(xiàn)(注:JAVA 8 之前一般是用匿名類實(shí)現(xiàn)的):

  1. GreetingService greetService1  
  2. = message -> System.out.println("Hello " + message); 

六、注解的使用場(chǎng)景

1、注解的官方釋義

注解是一系列元數(shù)據(jù),它提供數(shù)據(jù)用來(lái)解釋程序代碼,但是注解并非是所解釋的代碼本身的一部分。注解對(duì)于代碼的運(yùn)行效果沒(méi)有直接影響。

2、注解的用處

① 提供信息給編譯器:編譯器可以利用注解來(lái)探測(cè)錯(cuò)誤或警告信息

② 編譯階段時(shí)的處理:軟件工具可以利用注解信息來(lái)生成代碼、HTML文檔或其它響應(yīng)處理。

③ 運(yùn)行時(shí)的處理:某些注解可以在程序運(yùn)行時(shí)接受代碼的提取。

值得注意的是,注解不是代碼本身的一部分。

3、注解的用法舉例

  1. public class ExampleUnitTest { 
  2.     @Test 
  3.     public void addition_isCorrect() throws Exception { 
  4.         assertEquals(4, 2 + 2); 
  5.     } 

@Test 標(biāo)記了要進(jìn)行測(cè)試的方法 addition_isCorrect().

還有例如ssm框架等運(yùn)用了大量的注解。

七、注解的本質(zhì)

注解本質(zhì)是一個(gè)繼承了Annotation的特殊接口,其具體實(shí)現(xiàn)類是Java運(yùn)行時(shí)生成的動(dòng)態(tài)代理類。通過(guò)代理對(duì)象調(diào)用其自定義注解的方法,最終調(diào)用的是AnnotationInvocationHandler的invoke方法,該方法會(huì)從memberValues這個(gè)map中索引出對(duì)應(yīng)的值,而memberValues的來(lái)源是Java常量池。

八、總結(jié)

1、注解就是標(biāo)簽,注解為了解釋代碼

2、注解的基本語(yǔ)法@interface

3、注解的元注解

4、注解的屬性

5、注解主要給編譯器及工具類型的軟件用的

6、注解的提取要借助于Java的反射技術(shù),反射比較慢,所以注解使用時(shí)也需要謹(jǐn)慎計(jì)較時(shí)間成本

 本文轉(zhuǎn)載自微信公眾號(hào)「哪吒學(xué)Java」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系哪吒學(xué)Java公眾號(hào)。

 

 

責(zé)任編輯:武曉燕 來(lái)源: 哪吒學(xué)Java
相關(guān)推薦

2021-10-11 10:12:02

機(jī)器人人工智能系統(tǒng)

2018-05-23 11:43:59

數(shù)據(jù)庫(kù)

2015-07-14 11:39:08

Docker容器DevOps虛擬機(jī)

2016-01-26 17:47:58

SaaSSaaS平臺(tái)SaaS服務(wù)

2019-03-05 10:03:17

阿里云云廠商硬盤(pán)

2011-09-23 09:41:02

2015-03-10 10:32:21

蘋(píng)果2015MacBook Air

2024-08-30 17:25:23

開(kāi)發(fā)AI

2010-04-27 10:13:27

IPv4IPv6

2015-11-16 11:50:37

流量提速降費(fèi)運(yùn)營(yíng)商

2019-01-21 10:12:58

拼多多漏洞黑灰產(chǎn)

2009-04-21 15:07:02

2009-07-15 13:01:47

2015-11-16 11:03:59

流量提速降費(fèi)運(yùn)營(yíng)商

2019-11-01 18:57:44

戴爾

2021-03-16 14:43:23

比特幣加密貨幣貨幣

2024-04-01 00:35:00

AI數(shù)據(jù)

2020-08-08 13:33:12

微信禁令美國(guó)

2024-11-01 13:34:58

2014-08-22 17:19:12

經(jīng)營(yíng)信息化
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)