成熟丰满熟妇高潮XXXXX,人妻无码AV中文系列久久兔费 ,国产精品一国产精品,国精品午夜福利视频不卡麻豆

您好,歡迎來到九壹網(wǎng)。
搜索
您的當(dāng)前位置:首頁java注解的使用_Java注解的使用

java注解的使用_Java注解的使用

來源:九壹網(wǎng)

Java注解的使用

參考

廖雪峰java教程

使用注解

什么是注解(Annotation)?注解是放在Java源碼的類、方法、字段、參數(shù)前的一種特殊“注釋”:

注解的作用

從JVM的角度看,注解本身對代碼邏輯沒有任何影響,如何使用注解完全由工具決定。

Java的注解可以分為三類:

第一類是由編譯器使用的注解,例如:

@Override:讓編譯器檢查該方法是否正確地實現(xiàn)了覆寫;

@SuppressWarnings:告訴編譯器忽略此處代碼產(chǎn)生的警告。

這類注解不會被編譯進(jìn)入.class文件,它們在編譯后就被編譯器扔掉了。

第二類是由工具處理.class文件使用的注解,比如有些工具會在加載class的時候,對class做動態(tài)修改,實現(xiàn)一些特殊的功能。這類注解會被編譯進(jìn)入.class文件,但加載結(jié)束后并不會存在于內(nèi)存中。這類注解只被一些底層庫使用,一般我們不必自己處理。

第三類是在程序運行期能夠讀取的注解,它們在加載后一直存在于JVM中,這也是最常用的注解。例如,一個配置了@PostConstruct的方法會在調(diào)用構(gòu)造方法后自動被調(diào)用(這是Java代碼讀取該注解實現(xiàn)的功能,JVM并不會識別該注解)。

定義一個注解時,還可以定義配置參數(shù)。配置參數(shù)可以包括:

所有基本類型;

String;

枚舉類型;

基本類型、String、Class以及枚舉的數(shù)組。

因為配置參數(shù)必須是常量,所以,上述保證了注解在定義時就已經(jīng)確定了每個參數(shù)的值。

注解的配置參數(shù)可以有默認(rèn)值,缺少某個配置參數(shù)時將使用默認(rèn)值。

此外,大部分注解會有一個名為value的配置參數(shù),對此參數(shù)賦值,可以只寫常量,相當(dāng)于省略了value參數(shù)。

如果只寫注解,相當(dāng)于全部使用默認(rèn)值。

小結(jié)

注解(Annotation)是Java語言用于工具處理的標(biāo)注:

注解可以配置參數(shù),沒有指定配置的參數(shù)使用默認(rèn)值;

如果參數(shù)名稱是value,且只有一個參數(shù),那么可以省略參數(shù)名稱。

定義注解

Java語言使用@interface語法來定義注解(Annotation),它的格式如下:

@Target({ElementType.METHOD,ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Logger {

String value() default "";

String level() default "error";

int type() default 0;

}

注解的參數(shù)類似無參數(shù)方法,可以用default設(shè)定一個默認(rèn)值(強烈推薦)。最常用的參數(shù)應(yīng)當(dāng)命名為value。

元注解

有一些注解可以修飾其他注解,這些注解就稱為元注解(meta annotation)。Java標(biāo)準(zhǔn)庫已經(jīng)定義了一些元注解,我們只需要使用元注解,通常不需要自己去編寫元注解。

@Target

實際上@Target定義的value是ElementType[]數(shù)組,只有一個元素時,可以省略數(shù)組的寫法

最常用的元注解是@Target。使用@Target可以定義Annotation能夠被應(yīng)用于源碼的哪些位置:

類或接口:ElementType.TYPE;

字段:ElementType.FIELD;

方法:ElementType.METHOD;

構(gòu)造方法:ElementType.CONSTRUCTOR;

方法參數(shù):ElementType.PARAMETER。

@Retention

另一個重要的元注解@Retention定義了Annotation的生命周期:

僅編譯期:RetentionPolicy.SOURCE;

僅class文件:RetentionPolicy.CLASS;

運行期:RetentionPolicy.RUNTIME。

如果@Retention不存在,則該Annotation默認(rèn)為CLASS。因為通常我們自定義的Annotation都是RUNTIME,所以,務(wù)必要加上@Retention(RetentionPolicy.RUNTIME)這個元注解

@Repeatable

使用@Repeatable這個元注解可以定義Annotation是否可重復(fù)。這個注解應(yīng)用不是特別廣泛。

@Repeatable(Loggers.class)

@Target({ElementType.METHOD,ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Logger {

String value() default "";

String level() default "error";

int type() default 0;

}

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.TYPE,ElementType.METHOD})

public @interface Loggers {

Logger[] value();

}

經(jīng)過@Repeatable修飾后,在某個類型聲明處,就可以添加多個@Report注解:

@Logger(type=1, level="debug")

@Logger(type=2, level="warning")

public class Hello {

}

@Inherited——注解繼承,作用于類上

使用@Inherited定義子類是否可繼承父類定義的Annotation。@Inherited僅針對@Target(ElementType.TYPE)類型的annotation有效,并且僅針對class的繼承,對interface的繼承無效。

@Inherited

@Repeatable(Loggers.class)

@Target({ElementType.METHOD,ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Logger {

String value() default "";

String level() default "error";

int type() default 0;

}

在使用的時候,如果一個類用到了@Logger:

@Logger(type=1)

public class Person {

}

則它的子類默認(rèn)也定義了該注解:

public class Student extends Person {

}

如何定義Annotation

我們總結(jié)一下定義Annotation的步驟:

第一步,用@interface定義注解。

第二步,添加參數(shù)、默認(rèn)值。把最常用的參數(shù)定義為value(),推薦所有參數(shù)都盡量設(shè)置默認(rèn)值。

第三步,用元注解配置注解。其中,必須設(shè)置@Target和@Retention,@Retention一般設(shè)置為RUNTIME,因為我們自定義的注解通常要求在運行期讀取。一般情況下,不必寫@Inherited和@Repeatable。

小結(jié)

Java使用@interface定義注解:

可定義多個參數(shù)和默認(rèn)值,核心參數(shù)使用value名稱;

必須設(shè)置@Target來指定Annotation可以應(yīng)用的范圍;

應(yīng)當(dāng)設(shè)置@Retention(RetentionPolicy.RUNTIME)便于運行期讀取該Annotation。

處理注解

Java的注解本身對代碼邏輯沒有任何影響。根據(jù)@Retention的配置:

SOURCE類型的注解在編譯期就被丟掉了;

CLASS類型的注解僅保存在class文件中,它們不會被加載進(jìn)JVM;

RUNTIME類型的注解會被加載進(jìn)JVM,并且在運行期可以被程序讀取。

如何使用注解完全由工具決定。SOURCE類型的注解主要由編譯器使用,因此我們一般只使用,不編寫。CLASS類型的注解主要由底層工具庫使用,涉及到class的加載,一般我們很少用到。只有RUNTIME類型的注解不但要使用,還經(jīng)常需要編寫。

因此,我們只討論如何讀取RUNTIME類型的注解。

因為注解定義后也是一種class,所有的注解都繼承自java.lang.annotation.Annotation,因此,讀取注解,需要使用反射API。

Java提供的使用反射API讀取Annotation的方法包括:

判斷某個注解是否存在于Class、Field、Method或Constructor:

Class.isAnnotationPresent(Class)

Field.isAnnotationPresent(Class)

Method.isAnnotationPresent(Class)

Constructor.isAnnotationPresent(Class)

讀取方法、字段和構(gòu)造方法的Annotation和Class類似。但要讀取方法參數(shù)的Annotation就比較麻煩一點,因為方法參數(shù)本身可以看成一個數(shù)組,而每個參數(shù)又可以定義多個注解,所以,一次獲取方法參數(shù)的所有注解就必須用一個二維數(shù)組來表示。

示例:

public class AnnotationTest {

public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException {

UserController userController = new UserController();

boolean present = userController.getClass().isAnnotationPresent(Logger.class);

if (present) {

Logger logger = userController.getClass().getAnnotation(Logger.class);

System.out.println(" logger value: " + logger.value());

System.out.println(" logger level: " + logger.level());

}

Method loadUsers = UserController.class.getMethod("loadUsers");

Logger loadUsersAnnotation = loadUsers.getAnnotation(Logger.class);

if (loadUsersAnnotation != null) {

System.out.println("loadUsers logger value: " + loadUsersAnnotation.value());

System.out.println("loadUsers logger level: " + loadUsersAnnotation.level());

}

Method getUser = UserController.class.getMethod("getUser", String.class);

Annotation[][] annotations = getUser.getParameterAnnotations();

for (Annotation[] annotationArr : annotations) {

for (Annotation annotation : annotationArr) {

if (annotation instanceof NotEmpty) {

NotEmpty r = (NotEmpty) annotation;

System.out.println("NotEmpty");

}

if (annotation instanceof RequestParam) {

RequestParam r = (RequestParam) annotation;

System.out.println("RequestParam");

}

}

}

User user = new User();

//user.setName("牛掰");

user.setName("");

boolean checkEmpty = AnnotationTest.checkEmpty(user);

if (checkEmpty) {

System.out.println("一切正常!");

}

}

public static boolean checkEmpty(User user) throws IllegalAccessException {

Field[] declaredFields = user.getClass().getDeclaredFields();

if (declaredFields != null) {

// 遍歷所有Field:

for (Field field : declaredFields) {

field.setAccessible(true);

// 獲取Field定義的@Range:

NotEmpty range = field.getAnnotation(NotEmpty.class);

// 如果@Range存在:

if (range != null) {

// 獲取Field的值:

Object value = field.get(user);

// 如果值是String:

if (value == null) {

if (value instanceof String) {

String s = (String) value;

if (StringUtils.isEmpty(s)) {

throw new IllegalArgumentException("Invalid field: " + field.getName());

}

}

}else {

throw new IllegalArgumentException("Invalid field: " + field.getName());

}

}

}

}

return true;

}

}

輸出:

logger value: UserControllerLog

logger level: debug

loadUsers logger value: UserControllerLog.loadUsers

loadUsers logger level: info

NotEmpty

RequestParam

Exception in thread "main" java.lang.IllegalArgumentException: Invalid field: name

at com.self.annotation.AnnotationTest.checkEmpty(AnnotationTest.java:)

at com.self.annotation.AnnotationTest.main(AnnotationTest.java:61)

因篇幅問題不能全部顯示,請點此查看更多更全內(nèi)容

Copyright ? 2019- 91gzw.com 版權(quán)所有 湘ICP備2023023988號-2

違法及侵權(quán)請聯(lián)系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市萬商天勤律師事務(wù)所王興未律師提供法律服務(wù)