欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中的注解詳解(Annotation)

 更新時(shí)間:2025年03月04日 09:41:32   作者:小寶945  
文章介紹了Java中的注解,包括注解的定義、元注解、Java內(nèi)置的三大注解、自定義注解、反射注解以及注解的作用,注解是一種特殊的標(biāo)記,可以用于類(lèi)、方法、字段等元素,用于提供元數(shù)據(jù)信息

所有的注解類(lèi)型都繼承自 java.lang.annotation.Annotation 接口。

注解(Annotation)是一種引用數(shù)據(jù)類(lèi)型。編譯之后也是生成 xxx.class 文件。

一個(gè)注解準(zhǔn)確意義上來(lái)說(shuō),只不過(guò)是一種特殊的注釋而已,如果沒(méi)有解析它的代碼,它可能連注釋都不如。

解析一個(gè)類(lèi)或者方法的注解往往有兩種形式

一種是編譯期直接的掃描。=====> @Retention(RetentionPolicy.SOURCE)

  • 編譯器的掃描指的是編譯器在對(duì) java 代碼編譯字節(jié)碼的過(guò)程中會(huì)檢測(cè)到某個(gè)類(lèi)或者方法被一些注解修飾,這時(shí)它就會(huì)對(duì)于這些注解進(jìn)行某些處理。典型的就是 @Override 注解。
  • 這一種情況只適用于那些編譯器已經(jīng)熟知的注解類(lèi),比如 JDK 內(nèi)置的幾個(gè)注解,而你自定義的注解,編譯器是不知道你這個(gè)注解的作用的,當(dāng)然也不知道該如何處理,往往只是會(huì)根據(jù)該注解的作用范圍來(lái)選擇是否編譯進(jìn)字節(jié)碼文件,僅此而已。

一種是運(yùn)行期反射。====> @Retention(RetentionPolicy.RUNTIME)

一、元注解

  • 元注解是用于修飾注解的注解,通常用在注解的定義上。
  • 元注解一般用于指定某個(gè)注解生命周期以及作用目標(biāo)等信息。

Java 中的元注解

@Target:注解的作用目標(biāo)

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
	/**
 	* Returns an array of the kinds of elements an annotation interface
 	* can be applied to.
 	* @return an array of the kinds of elements an annotation interface
 	* can be applied to
 	*/
	ElementType[] value();
}
  • ElementType.TYPE:允許被修飾的注解作用在類(lèi)、接口和枚舉上
  • ElementType.FIELD:允許作用在屬性字段上
  • ElementType.METHOD:允許作用在方法上
  • ElementType.PARAMETER:允許作用在方法參數(shù)上
  • ElementType.CONSTRUCTOR:允許作用在構(gòu)造器上
  • ElementType.LOCAL_VARIABLE:允許作用在本地局部變量上
  • ElementType.ANNOTATION_TYPE:允許作用在注解上
  • ElementType.PACKAGE:允許作用在包上

@Retention:注解的生命周期

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
   /**
 	* Returns the retention policy.
  	* @return the retention policy
	*/
	RetentionPolicy value();
}
  • RetentionPolicy.SOURCE:當(dāng)前注解編譯期可見(jiàn),不會(huì)寫(xiě)入 class 文件
  • RetentionPolicy.CLASS:類(lèi)加載階段丟棄,會(huì)寫(xiě)入 class 文件
  • RetentionPolicy.RUNTIME:永久保存,可以反射獲取

@Documented:注解是否應(yīng)當(dāng)被包含在 JavaDoc 文檔中

@Inherited:是否允許子類(lèi)繼承該注解

二、Java 中內(nèi)置的三大注解

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

它沒(méi)有任何的屬性,所以并不能存儲(chǔ)任何其他信息。它只能作用于方法之上,編譯結(jié)束后將被丟棄。

僅被編譯器可知,編譯器在對(duì) java 文件進(jìn)行編譯成字節(jié)碼的過(guò)程中,一旦檢測(cè)到某個(gè)方法上被修飾了該注解,就會(huì)去匹對(duì)父類(lèi)中是否具有一個(gè)同樣方法簽名的函數(shù),如果不是,自然不能通過(guò)編譯。

  • @Deprecated
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
public @interface Deprecated {
    String since() default "";
    boolean forRemoval() default false;
}

可以修飾所有的類(lèi)型,作用是,標(biāo)記當(dāng)前的類(lèi)或者方法或者字段等已經(jīng)不再被推薦使用了,可能下一次的 JDK 版本就會(huì)刪除。

  • @SuppressWarnings

三、自定義注解

語(yǔ)法格式:

[修飾符列表] @interface 注解類(lèi)型名{
	類(lèi)型 屬性() [defauult 值];
}
// 樣例
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String name() default "gdb";
    String[] phoneNumbers() default {};
}

注解當(dāng)中的屬性類(lèi)型可以是:byte short int long float double boolean char String Class 枚舉類(lèi)型以及以上每一種的數(shù)組形式。

四、反射注解

要求必須使用 @Retention(RetentionPolicy.RUNTIME),這樣該注解才能夠被反射到。

例子:反射類(lèi)上的 @MyAnnotation 注解。

  • 1.編寫(xiě)自己的注解:
package annotation1;

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 MyAnnotation {
    String name() default "gdb";
    String[] phoneNumbers() default {};
}	
  • 2.在類(lèi)上使用自己的注解:
package annotation1;

@MyAnnotation(name = "zhangsan", phoneNumbers = {"123456", "654321"})
public class MyAnnotationTest {

}
  • 3.通過(guò)反射機(jī)制來(lái)獲取指定類(lèi)上的注解信息:
package annotation1;

import java.util.Arrays;

public class ReflectAnnotation {
    public static void main(String[] args) throws Exception {
        //獲取類(lèi)
        Class<?> c = Class.forName("annotation1.MyAnnotationTest");
        //判斷類(lèi)上面是否有 @MyAnnotation
        if (c.isAnnotationPresent(MyAnnotation.class)){
            //獲取注解對(duì)象
            MyAnnotation myAnnotation = (MyAnnotation)c.getAnnotation(MyAnnotation.class);
            //獲取注解對(duì)象的屬性和調(diào)用接口沒(méi)有區(qū)別
            System.out.println(myAnnotation.name() + ", " + Arrays.toString(myAnnotation.phoneNumbers()));
        }
        //判斷 Date 類(lèi)上面是否有 @MyAnnotation 這個(gè)注解。
        Class<?> s = Class.forName("java.lang.String");
        System.out.println(s.isAnnotationPresent(MyAnnotation.class));
    }
}

五、注解的作用

注解在程序當(dāng)中等同于一種標(biāo)記,如果這個(gè)元素上有這個(gè)注解怎么辦,沒(méi)有這個(gè)注解怎么辦。

應(yīng)用場(chǎng)景:假設(shè)有這樣一個(gè)注解,叫做 @Id,這個(gè)注解只能出現(xiàn)在類(lèi)上面,當(dāng)這個(gè)類(lèi)上有這個(gè)注解的時(shí)候,要求這個(gè)類(lèi)中必須有一個(gè) int 類(lèi)型的 id 屬性。如果沒(méi)有這個(gè)屬性就報(bào)異常。如果有這個(gè)屬性就正常執(zhí)行。

  • 1.編寫(xiě) @Id 注解:
package annotation1;

public class NotHasIdException extends RuntimeException{
    public NotHasIdException() {
    }

    public NotHasIdException(String message) {
        super(message);
    }
}
  • 2.編寫(xiě)異常類(lèi):
package annotation1;

public class NotHasIdException extends RuntimeException{
    public NotHasIdException() {
    }

    public NotHasIdException(String message) {
        super(message);
    }
}
  • 3.編寫(xiě)使用 @Id 注解的類(lèi):
package annotation1;

@Id
public class IdAnnotationTest {
    int id;
}
  • 4.通過(guò)反射機(jī)制來(lái)判斷是否正確:
package annotation1;

import java.lang.reflect.Field;

public class ReflectAnnotation {
    public static void main(String[] args) throws Exception {
        //獲取類(lèi)
        Class<?> c = Class.forName("annotation1.IdAnnotationTest");
        //判斷類(lèi)上面是否有 @Id 注解
        if (c.isAnnotationPresent(Id.class)){
            //當(dāng)一個(gè)類(lèi)上面有 @Id 注解的時(shí)候,要求類(lèi)中必須存在 int 類(lèi)型的id屬性。
            //如果沒(méi)有int類(lèi)型的id屬性則報(bào)異常。
            //獲取類(lèi)的所有屬性
            Field[] fields = c.getDeclaredFields();
            boolean isOK = false;
            for(Field field : fields){
                if("id".equals(field.getName()) && "int".equals(field.getType().getSimpleName())){
                    isOK = true;
                    break;
                }
            }
            //判斷是否合法
            if (!isOK)
                throw new NotHasIdException("被@Id注解標(biāo)注的類(lèi)沒(méi)有int類(lèi)型的id屬性?。。?);
        }
    }
}

六、總結(jié)

  • 如果一個(gè)注解的屬性的名字是 value,并且只有一個(gè)屬性的話,在使用的時(shí)候,該屬性名可以省略。
  • 如果屬性是一個(gè)數(shù)組,如果數(shù)組中只有一個(gè)元素,大括號(hào)可以省略。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解Java的MyBatis框架中的緩存與緩存的使用改進(jìn)

    詳解Java的MyBatis框架中的緩存與緩存的使用改進(jìn)

    很多人在使用MyBatis的緩存后經(jīng)常會(huì)遇到MySQL分頁(yè)查詢(xún)的顯示問(wèn)題,針對(duì)于此,這里我們就來(lái)詳解Java的MyBatis框架中的緩存與緩存的使用改進(jìn),首先來(lái)回顧一下MyBatis的緩存機(jī)制與執(zhí)行:
    2016-06-06
  • RabbitMQ消息丟失解決方案

    RabbitMQ消息丟失解決方案

    把這篇文章主要為大家介紹了如何保證RabbitMQ消息不丟失的解決方發(fā),分從從丟失的三種情況給大家介紹不同的解決方案,感興趣的小伙伴可以參考閱讀本文
    2023-07-07
  • Springboot詳解RocketMQ實(shí)現(xiàn)消息發(fā)送與接收流程

    Springboot詳解RocketMQ實(shí)現(xiàn)消息發(fā)送與接收流程

    這篇文章主要介紹了SpringBoot整合RocketMQ實(shí)現(xiàn)消息發(fā)送和接收功能,我們使用主流的SpringBoot框架整合RocketMQ來(lái)講解,使用方便快捷,本文分步驟給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • 詳解Java如何在業(yè)務(wù)代碼中優(yōu)雅的使用策略模式

    詳解Java如何在業(yè)務(wù)代碼中優(yōu)雅的使用策略模式

    這篇文章主要為大家介紹了Java如何在業(yè)務(wù)代碼中優(yōu)雅的使用策略模式,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的可以了解下
    2023-08-08
  • 在lambda的foreach遍歷中break退出操作(lambda foreach break)

    在lambda的foreach遍歷中break退出操作(lambda foreach break)

    這篇文章主要介紹了在lambda的foreach遍歷中break退出操作(lambda foreach break),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • springboot開(kāi)發(fā)擴(kuò)展springmvc實(shí)現(xiàn)解析

    springboot開(kāi)發(fā)擴(kuò)展springmvc實(shí)現(xiàn)解析

    這篇文章主要介紹了springboot開(kāi)發(fā)擴(kuò)展springmvc實(shí)現(xiàn)解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • Java中Map實(shí)現(xiàn)線程安全的3種方式

    Java中Map實(shí)現(xiàn)線程安全的3種方式

    本文主要介紹了Java中Map實(shí)現(xiàn)線程安全的3種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Java遍歷Map的方法匯總

    Java遍歷Map的方法匯總

    大家平時(shí)在使用Java開(kāi)發(fā)時(shí),經(jīng)常會(huì)遇到遍歷Map對(duì)象的問(wèn)題,本文就給大家介紹幾種Java遍歷Map對(duì)象的方法,并簡(jiǎn)單分析一下每種方法的效率,需要的朋友可以參考下
    2023-12-12
  • java編程實(shí)現(xiàn)基于UDP協(xié)議傳輸數(shù)據(jù)的方法

    java編程實(shí)現(xiàn)基于UDP協(xié)議傳輸數(shù)據(jù)的方法

    這篇文章主要介紹了java編程實(shí)現(xiàn)基于UDP協(xié)議傳輸數(shù)據(jù)的方法,較為詳細(xì)的分析了UDP協(xié)議的原理及Java編程實(shí)現(xiàn)數(shù)據(jù)傳輸客戶(hù)端與服務(wù)器端的相關(guān)技巧,需要的朋友可以參考下
    2015-11-11
  • MyBatis-Plus 批量插入數(shù)據(jù)的操作方法

    MyBatis-Plus 批量插入數(shù)據(jù)的操作方法

    spring boot+mybatis plus環(huán)境,單條插入用的是BaseMapper自帶的insert方法,本文重點(diǎn)給大家介紹MyBatis-Plus 批量插入數(shù)據(jù)的操作方法,感興趣的朋友一起看看吧
    2021-09-09

最新評(píng)論