欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報邀請碼778899分享:開發(fā)語言 Java-注解詳解

柚子快報邀請碼778899分享:開發(fā)語言 Java-注解詳解

http://yzkb.51969.com/

1?? 注解的含義

注解(Annotation)是Java語言中一種特殊的修飾符,它可以用于類、方法、參數(shù)、變量、構(gòu)造器以及包聲明中,用于為Java代碼提供元數(shù)據(jù)。相對于其他修飾符如public、final等,注解并不直接影響代碼的語義,但卻能被某些工具軟件(如編譯器、框架)所讀取和利用。

? 注解的主要作用

編譯檢查 - 如@Override放在方法前,如果該方法不是重寫父類的方法,則編譯器會發(fā)出警告。代碼分析 - 通過代碼里標(biāo)識的注解,程序可以在編譯時進(jìn)行一些基于注解的處理。注解信息和JAVA的反射功能在一起時會使得程序的功能更加強大。編譯時動態(tài)處理 - 如常見的Java框架Spring、Hibernate、JUnit等,會在編譯時讀取注解的信息,然后根據(jù)注解的信息進(jìn)行一些其他處理。生成額外的文件 - 如Javadoc工具會根據(jù)源碼中的注解來生成API文檔。

? 注解的基本語法

注解的聲明類似于接口的聲明,但是前面多了一個@符號:

public @interface MyAnnotation {

String value() default ""; //定義value屬性

}

使用注解:

@MyAnnotation(value="This is my custom annotation")

public class MyClass {

// class body

}

? 內(nèi)置注解

Java提供了一些預(yù)定義的注解,如:

@Override: 限定重寫父類方法。@Deprecated: 表示某個程序元素(如方法)已經(jīng)過時。@SuppressWarnings: 告訴編譯器忽略指定的警告。

? 元注解

用于注解其他注解的注解稱為元注解。Java提供了以下幾種元注解:

@Target: 表明該注解可以被應(yīng)用于什么地方(如方法、類、字段等)。@Retention: 表明該注解的生命周期(僅源代碼、編譯期、運行期)。@Documented: 表示使用該注解的元素應(yīng)被Javadoc或其他工具文檔化。@Inherited: 表示該注解可以被子類繼承。

注解為Java提供了一種元級編程的方式,它允許開發(fā)者在不修改代碼邏輯的前提下,向源碼中添加一些額外的信息,這些信息可以被編譯器或其他工具所讀取并使用。

2?? 注解分類

由編譯器使用的注解

含義:這類注解不會被編譯進(jìn)入 .class 文件,在編譯后它們就被編譯器丟棄了。示例:

@Override:此注解讓編譯器檢查該方法是否正確地實現(xiàn)了覆寫。@SuppressWarnings:此注解告訴編譯器忽略此處代碼產(chǎn)生的警告。 由工具處理 .class 文件使用的注解

含義:有些工具在加載 class 的時候,會對 class 文件做動態(tài)修改,以實現(xiàn)一些特殊的功能。這類注解會被編譯進(jìn)入 .class 文件,但在加載完成后并不會存在于內(nèi)存中。這類注解主要被一些底層庫使用,一般我們不需要自己處理。示例:可以參考 lombok。 在程序運行期能夠讀取的注解

含義:這些注解在加載后會一直存在于 JVM 中,是最常用的注解。示例:配置了 @PostConstruct 的方法會在調(diào)用構(gòu)造方法后自動被調(diào)用。這是 Java 代碼通過讀取該注解實現(xiàn)的功能,JVM 本身并不會識別該注解。

3?? 元注解(java.lang.annotation下的注解:用來定義注解的)

Java 的注解為代碼添加了額外的元數(shù)據(jù),這些元數(shù)據(jù)在編譯或運行時都可以被訪問。為了定義注解的屬性和行為,Java 提供了以下一系列的元注解:

? @Retention

描述:確定注解的生命周期,即何時可用。用途:通知開發(fā)者注解在何時應(yīng)被使用或訪問。示例:@Retention(RetentionPolicy.RUNTIME)

public @interface MyAnnotation { }

? @Target

描述:指定注解可以應(yīng)用的源碼元素。用途:避免注解被誤用在不適當(dāng)?shù)牡胤?,限制注解的適用范圍。示例:@Target(ElementType.METHOD)

public @interface MyMethodAnnotation { }

? @Inherited

描述:允許子類繼承父類上的注解。用途:當(dāng)需要子類自動繼承父類的注解時使用。示例:@Inherited

public @interface Inheritable { }

? @Documented

描述:注解信息會被包含在 Javadoc 中。用途:確保開發(fā)者在查看 API 文檔時,可以看到注解的信息。示例:@Documented

public @interface DocumentedAnnotation { }

? @Repeatable (Java 8 新增)

描述:允許同一個注解在同一聲明上使用多次。用途:在 Java 8 之前,一個注解在同一位置只能使用一次,此元注解允許多次使用同一個注解。示例:public @interface RepeatedValues {

Value[] value();

}

@Repeatable(RepeatedValues.class)

public @interface Value {

String info() default "";

}

4?? JDK 內(nèi)置注解(都屬于由編譯器使用的注解)

在 java.lang 包中,JDK 提供了五個基本注解:

? @Override

描述:用于指定子類中的方法重寫了父類的方法。用法:

告知編譯器我們意圖重寫父類方法。如果子類的方法與父類方法簽名不匹配,編譯器會報錯。 適用范圍:只能用于方法。

? @Deprecated

描述:用于標(biāo)記已過時的程序元素,如類、方法等。用法:

提醒開發(fā)者不建議使用該程序元素。使用被此注解標(biāo)記的元素時,編譯器會給出警告。

? @SuppressWarnings

描述:用于抑制編譯器產(chǎn)生警告。用法:告知編譯器忽略特定的警告。常見參數(shù):

deprecation:使用已過時的類或方法。unchecked:未經(jīng)檢查的類型轉(zhuǎn)換。fallthrough:switch 語句缺少 break。path:類或源文件路徑不存在。serial:可序列化類缺少 serialVersionUID。finally:finally 語句未正常完成。all:上述所有情況。

? @SafeVarargs

描述:抑制堆污染警告。特點:JDK 7 新增,用于標(biāo)記可能產(chǎn)生堆污染的方法或構(gòu)造函數(shù)。

? @FunctionalInterface (Java 8 新增)

描述:標(biāo)記一個接口為函數(shù)式接口。定義:接口中只有一個抽象方法(但可以有多個 default 或 static 方法)。

?注意事項

value 特權(quán):如果注解的 value 成員變量是唯一需要賦值的,可以省略 name=value 的格式,直接在注解的括號中指定值。 推薦使用 @Override:在意圖重寫父類方法的每個方法上使用 @Override,幫助編譯器及時捕獲可能的錯誤。

5?? 自定義注解

在 Java 中,注解是一種為代碼添加元數(shù)據(jù)的方式。當(dāng)我們使用 @interface 關(guān)鍵字定義新的注解時,背后的一些細(xì)節(jié)會由編譯器自動完成,例如自動繼承 java.lang.annotation.Annotation 接口。

? 注解的定義規(guī)則:

在定義新注解時,不能繼承其他注解或接口。@interface 關(guān)鍵字用于聲明一個新的注解。在注解內(nèi),每個方法都代表一個配置參數(shù)。

方法名為參數(shù)名。返回值類型定義了參數(shù)的類型。方法可以沒有參數(shù)??梢允褂?default 關(guān)鍵字為參數(shù)設(shè)定默認(rèn)值。

? 注解參數(shù)的支持類型:

基本數(shù)據(jù)類型:如 int, float, boolean, byte, double, char, long, shortStringClass枚舉類型 (Enum)其他注解 (Annotation)以上所有類型的數(shù)組形式

package annotation.custom;

// 導(dǎo)入必要的注解處理類

import java.lang.annotation.ElementType;

import java.lang.annotation.Inherited;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

// 表明這個注解是可以被子類繼承的

@Inherited

// 指明該注解的生命周期,此處指定為RUNTIME,表示注解在運行時仍然存在,并可以通過反射機(jī)制讀取

@Retention(RetentionPolicy.RUNTIME)

// 指明該注解可以被應(yīng)用于方法和類型(類、接口、枚舉、注解)

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

public @interface Tag {

// 定義一個名為name的元素,它的默認(rèn)值為"undefined"

String name() default "undefined";

// 定義一個名為description的元素,使用該注解時,這個元素是必須要設(shè)置的,因為它沒有默認(rèn)值

String description();

}

// 代表所有的注解類型

public interface Annotation {

// 用于比較兩個注解是否相等。注意:自定義的注解會有編譯器生成的實現(xiàn),所以使用者不需要手動實現(xiàn)此方法。

boolean equals(Object obj);

// 返回該注解的哈希碼。同樣,這個方法會由編譯器自動生成其實現(xiàn)。

int hashCode();

// 返回該注解的字符串表示形式。這也是由編譯器自動生成的方法。

String toString();

// 返回表示此注解的注解類型的Class對象。它可以用于在運行時獲取注解的信息。

Class annotationType();

}

注意: Java 使用 Annotation 接口來代表程序元素前面的注解,該接口是所有 Annotation 類型的父接口。 自定義的注解繼承了 Annotation 這個接口,因此自定義注解中包含了 Annotation 接口中所有的方法

6?? 注解的提取

Java在java.lang.reflect包內(nèi)提供了強大的反射機(jī)制,其中AnnotatedElement接口扮演了關(guān)鍵角色,代表那些可以攜帶注解的程序元素。

? AnnotatedElement接口

定義:此接口表示可以接受注解的程序元素。 實現(xiàn)類:

AccessibleObject:是Field、Method和Constructor對象的基類。Executable:是Method和Constructor對象的共有基類。Method:表示類或接口中的某個方法。Constructor:提供某個類的構(gòu)造方法的信息。Field:表示類或接口中的某個字段。Class:代表應(yīng)用程序中的類和接口。Package:提供有關(guān)Java包的版本信息。Parameter:提供關(guān)于方法參數(shù)的信息,Java 8 新增。 功能:通過這些類,Java提供了一套豐富的API用于獲取運行時的注解信息。

? 如何使用

只有當(dāng)一個注解被定義為運行時注解(即使用@Retention(RetentionPolicy.RUNTIME)標(biāo)注)時,它才會在運行時被JVM讀取。這意味著,通過反射,我們可以讀取類、方法或字段上的這些注解,并據(jù)此執(zhí)行某些操作。例如,通過反射獲得某個類的Method對象后,可以調(diào)用該對象的getAnnotations()方法來獲取所有的注解。

? 方法描述

isAnnotationPresent(Class annotationType):

描述:此方法用于判斷指定的對象是否應(yīng)用了某個注解。應(yīng)用:主要用于方便地訪問標(biāo)記注解。 getAnnotations():

描述:返回作用于指定對象的所有注解。注意:如果沒有,則返回長度為0的數(shù)組。 getDeclaredAnnotations():

描述:返回直接作用于指定對象的所有注解。注意:如果不存在,則返回長度為0的數(shù)組。此方法忽略繼承的注解。 getAnnotation(Class annotationClass):

描述:返回指定對象上的指定類型的注解。注意:如果注解不存在,則返回null。 getDeclaredAnnotation(Class annotationClass):

描述:返回直接作用于指定對象的指定類型的注解。注意:如果注解不存在,則返回null。此方法忽略繼承的注解。 getAnnotationsByType(Class annotationClass):

描述:返回指定對象上的指定類型的所有注解。注意:如果不存在,則返回長度為0的數(shù)組。此方法檢測其參數(shù)是否為可重復(fù)的注解類型。 getDeclaredAnnotationsByType(Class annotationClass):

描述:返回直接作用于指定對象的指定類型的所有注解。注意:如果不存在,則返回長度為0的數(shù)組。此方法檢測其參數(shù)是否為可重復(fù)的注解類型,并忽略繼承的注解。

注意: 只有當(dāng)定義 Annotation 時使用了 @Retention(RetentionPolicy.RUNTIME) 修飾, JVM 才會在裝載 class 文件時提取保存在 class 文件中的 Annotation, 該 Annotation 才會在運行時可見。否則class 文件的注解信息在執(zhí)行過程中將不可用, 從而也就不能從中得到任何和注解有關(guān)的數(shù)據(jù)。

7?? 注解處理器

? 注解處理器簡介

定義:注解處理器是用于在編譯時掃描、處理源代碼中的注解的工具。它可以分析注解并生成額外的源代碼或其他文件。歷史:

Java 5:首次引入注解,但處理注解的API不夠成熟。需要使用一個獨立的工具apt(Annotation Processor Tool)和com.sun.mirror包中的Mirror API來處理注解。Java 6:通過JSR 269,注解處理器被標(biāo)準(zhǔn)化并納入到Java標(biāo)準(zhǔn)庫中。apt工具被集成到j(luò)avac編譯工具中。Java 6提供了一個通用功能的抽象類javax.annotation.processing.AbstractProcessor和javax.lang.model包來支持注解處理。

? 如何工作

在編譯階段,javac會掃描每個源文件中的注解。對于每個找到的注解,javac會查詢是否有已注冊的注解處理器可以處理它。如果有,javac將調(diào)用該處理器來處理注解。處理器可以分析注解、讀取注解的值,并根據(jù)這些值生成額外的源代碼或其他文件。

? 注解處理器的用途

自動化代碼生成:允許開發(fā)者定義規(guī)則和模式,然后讓機(jī)器自動為我們生成代碼,避免了人為錯誤和重復(fù)勞動。編譯時檢查:通過注解處理器,我們可以在編譯時進(jìn)行更多的檢查,確保代碼的質(zhì)量和準(zhǔn)確性。性能:由于大部分工作在編譯時完成,運行時的性能開銷被最小化。代碼整潔:自動生成的代碼可以分離到另外的文件中,保持主要業(yè)務(wù)邏輯的代碼清晰和整潔。

? 應(yīng)用場景

類屬性自動賦值:

自動注入對象或值,例如Spring框架中的@Autowired和@Value。 驗證對象屬性完整性:

例如,使用Java Bean Validation API(如@NotNull, @Size, @Min, @Max等)進(jìn)行對象屬性驗證。 代替配置文件功能:

通過注解配置,如Spring的@Component, @Service, @Repository, @Controller等。 生成文檔:

Javadoc工具使用注解來生成API文檔。 編譯時檢查:

例如,@Override用于告訴編譯器子類中的某個方法是否正確地重寫了父類中的方法。 代碼生成:

編譯時注解處理器可以用于生成額外的源代碼。 運行時處理:

通過反射API在運行時讀取注解信息,如Spring AOP、JUnit等。 APT(Annotation Processing Tool):

處理和提取注解的工具或代碼。例如,Lombok庫使用注解處理器在編譯時生成getter、setter和其他常見方法。

? AbstractProcessor

AbstractProcessor 是一個提供便捷實現(xiàn)注解處理器功能的抽象類,實現(xiàn)了 Processor 接口,都位于 javax.annotation.processing 包中。

自定義注解處理器的主要步驟:

實現(xiàn) Processor 接口: 通過繼承 AbstractProcessor 類來實現(xiàn)自定義的注解處理器。主要的工作在于實現(xiàn) process 方法,進(jìn)行你想要完成的注解處理功能。 在 init() 方法中,你可以獲得:

Elements: 一個處理 Element 的工具類。Types: 用來處理 TypeMirror 的工具類。Filer: 用于創(chuàng)建文件。 在注解處理過程中,會掃描所有的 Java 源文件。每個部分都是一個特定類型的 Element,代表程序的元素,例如包、類或者方法。主要的子類有:

PackageElement: 代表一個包。TypeElement: 代表一個類或接口。VariableElement: 表示變量,如成員變量、枚舉常量、方法或構(gòu)造方法參數(shù)等。ExecutableElement: 表示類或接口的方法、構(gòu)造方法。TypeParameterElement: 表示類型參數(shù)。 注冊注解處理器: 有兩種方法:

手動注冊: 在項目的 resources/META-INF/services 目錄下新建文件 javax.annotation.processing.Processor,內(nèi)容是處理器的全稱。自動注冊: 使用 Google 提供的庫,添加 com.google.auto.service:auto-service 依賴,并在處理器上添加 @AutoService(Processor.class) 注解。這會自動在 META-INF 目錄下生成配置信息文件。

注意:在 Java 6 及以上版本中,可以使用 @SupportedAnnotationTypes 注解和 @SupportedSourceVersion 注解來分別替代 getSupportedAnnotationTypes() 方法和 getSupportedSourceVersion() 方法。

? 自定義注解處理器都需要繼承于 AbstractProcessor,如下所示:

/**

* 自定義注解處理器

*/

public class CustomProcessor extends AbstractProcessor {

private Filer mFiler;

private Messager mMessager;

private Elements mElementUtils;

@Override

public synchronized void init(ProcessingEnvironment processingEnvironment) {

super.init(processingEnvironment);

mFiler = processingEnvironment.getFiler();

mMessager = processingEnvironment.getMessager();

mElementUtils = processingEnvironment.getElementUtils();

}

@Override

public Set getSupportedAnnotationTypes() {

Set annotataions = new LinkedHashSet();

annotataions.add(Tag.class.getCanonicalName());

return annotataions;

}

@Override

public SourceVersion getSupportedSourceVersion() {

return SourceVersion.latestSupported();

}

@Override

public boolean process(Set annotations, RoundEnvironment roundEnvironment) {

Set tagElements = roundEnvironment.getElementsAnnotatedWith(Tag.class);

for (Element element : tagElements) {

// 1.獲取包名

PackageElement packageElement = mElementUtils.getPackageOf(element);

String pkName = packageElement.getQualifiedName().toString();

printMessage(String.format("package = %s", pkName));

// 2.獲取包裝類類型

TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();

String enclosingName = enclosingElement.getQualifiedName().toString();

printMessage(String.format("enclosindClass = %s", enclosingName));

// 3.獲取注解的成員變量名

String tagFiledName = element.getSimpleName().toString();

// 4.獲取注解的成員變量類型

String tagFiledClassType = element.asType().toString();

// 5.獲取注解元數(shù)據(jù)

Tag tag = element.getAnnotation(Tag.class);

String name = tag.name();

printMessage(String.format("%s %s = %s", tagFiledClassType, tagFiledName, name));

// 6.生成文件

createFile(enclosingElement, tagFiledClassType, tagFiledName, name);

return true;

}

return false;

}

private void createFile(TypeElement enclosingElement, String tagFiledClassType, String tagFiledName, String name) {

String pkName = mElementUtils.getPackageOf(enclosingElement).getQualifiedName().toString();

try {

JavaFileObject javaFileObject = mFiler.createSourceFile(pkName + ".Tag");

Writer writer = javaFileObject.openWriter();

writer.write(generateCode(pkName, tagFiledClassType, tagFiledName, name));

writer.flush();

writer.close();

} catch (IOException e) {

e.printStackTrace();

}

}

private void printMessage(String msg) {

mMessager.printMessage(Diagnostic.Kind.NOTE, msg);

}

private String generateCode(String pkName, String tagFiledClassType, String tagFiledName, String name) {

StringBuilder builder = new StringBuilder();

builder.append("package " + pkName + ";\n\n");

builder.append("http://Auto generated by apt,do not modify!!\n\n");

builder.append("public class Tag { \n\n");

builder.append("public static void main(String[] args){ \n");

String info = String.format("%s %s = %s", tagFiledClassType, tagFiledName, name);

builder.append("System.out.println(\"" + info + "\");\n");

builder.append("}\n");

builder.append("}");

return builder.toString();

}

}

柚子快報邀請碼778899分享:開發(fā)語言 Java-注解詳解

http://yzkb.51969.com/

推薦文章

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19263686.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄