`
zzc1684
  • 浏览: 1223179 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

Java基础笔记 – Annotation注解的介绍和使用 自定义注解

    博客分类:
  • Java
阅读更多
1、Annotation的工作原理:

JDK5.0中提供了注解的功能,允许开发者定义和使用自己的注解类型。该功能由一个定义注解类型的语法和描述一个注解声明的语法,读取注解的API,一个使用注解修饰的class文件和一个注解处理工具组成。

Annotation并不直接影响代码的语义,但是他可以被看做是程序的工具或者类库。它会反过来对正在运行的程序语义有所影响。

Annotation可以冲源文件、class文件或者在运行时通过反射机制多种方式被读取。

2、@Override注解:
java.lang
注释类型 Override
@Target(value=METHOD)
@Retention(value=SOURCE)
public @interface Override

表示一个方法声明打算重写超类中的另一个方法声明。如果方法利用此注释类型进行注解但没有重写超类方法,则编译器会生成一条错误消息。

@Override注解表示子类要重写父类的对应方法。

Override是一个Marker annotation,用于标识的Annotation,Annotation名称本身表示了要给工具程序的信息。

下面是一个使用@Override注解的例子:

class A {
    private String id;
    A(String id){
        this.id = id;
    }
    @Override
    public String toString() {
        return id;
    }
}
3、@Deprecated注解:
java.lang
注释类型 Deprecated
@Documented
@Retention(value=RUNTIME)
public @interface Deprecated

用 @Deprecated 注释的程序元素,不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。在使用不被赞成的程序元素或在不被赞成的代码中执行重写时,编译器会发出警告。

@Deprecated注解表示方法是不被建议使用的。

Deprecated是一个Marker annotation。

下面是一个使用@Deprecated注解的例子:

class A {
    private String id;
    A(String id){
        this.id = id;
    }
    @Deprecated
    public void execute(){
        System.out.println(id);
    }
    public static void main(String[] args) {
        A a = new A("a123");
        a.execute();
    }
}
4、@SuppressWarnings注解:
java.lang
注释类型 SuppressWarnings
@Target(value={TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE})
@Retention(value=SOURCE)
public @interface SuppressWarnings

指示应该在注释元素(以及包含在该注释元素中的所有程序元素)中取消显示指定的编译器警告。注意,在给定元素中取消显示的警告集是所有包含元素中取 消显示的警告的超集。例如,如果注释一个类来取消显示某个警告,同时注释一个方法来取消显示另一个警告,那么将在此方法中同时取消显示这两个警告。

根据风格不同,程序员应该始终在最里层的嵌套元素上使用此注释,在那里使用才有效。如果要在特定的方法中取消显示某个警告,则应该注释该方法而不是注释它的类。

@SuppressWarnings注解表示抑制警告。

下面是一个使用@SuppressWarnings注解的例子:

@SuppressWarnings("unchecked")
public static void main(String[] args) {
    List list = new ArrayList();
    list.add("abc");
}
5、自定义注解:

使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。

自定义最简单的注解:

public @interface MyAnnotation {

}

使用自定义注解:

public class AnnotationTest2 {

    @MyAnnotation
    public void execute(){
        System.out.println("method");
    }
}
5.1、添加变量:
public @interface MyAnnotation {

    String value1();
}

使用自定义注解:

public class AnnotationTest2 {

    @MyAnnotation(value1="abc")
    public void execute(){
        System.out.println("method");
    }
}

当注解中使用的属性名为value时,对其赋值时可以不指定属性的名称而直接写上属性值接口;除了value意外的变量名都需要使用name=value的方式赋值。

5.2、添加默认值:
public @interface MyAnnotation {

    String value1() default "abc";
}
5.3、多变量使用枚举:
public @interface MyAnnotation {

    String value1() default "abc";
    MyEnum value2() default MyEnum.Sunny;
}
enum MyEnum{
    Sunny,Rainy
}

使用自定义注解:

public class AnnotationTest2 {

    @MyAnnotation(value1="a", value2=MyEnum.Sunny)
    public void execute(){
        System.out.println("method");
    }
}
5.4、数组变量:
public @interface MyAnnotation {

    String[] value1() default "abc";
}

使用自定义注解:

public class AnnotationTest2 {

    @MyAnnotation(value1={"a","b"})
    public void execute(){
        System.out.println("method");
    }
}
6、设置注解的作用范围:
@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Retention

指示注释类型的注释要保留多久。如果注释类型声明中不存在 Retention 注释,则保留策略默认为 RetentionPolicy.CLASS。

只有元注释类型直接用于注释时,Target 元注释才有效。如果元注释类型用作另一种注释类型的成员,则无效。

public enum RetentionPolicy
extends Enum<RetentionPolicy>

注释保留策略。此枚举类型的常量描述保留注释的不同策略。它们与 Retention 元注释类型一起使用,以指定保留多长的注释。

CLASS
编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释。
RUNTIME
编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。
SOURCE
编译器要丢弃的注释。

@Retention注解可以在定义注解时为编译程序提供注解的保留策略。

属于CLASS保留策略的注解有@SuppressWarnings,该注解信息不会存储于.class文件。

6.1、在自定义注解中的使用例子:
@Retention(RetentionPolicy.CLASS)
public @interface MyAnnotation {

    String[] value1() default "abc";
}
7、使用反射读取RUNTIME保留策略的Annotation信息的例子:
java.lang.reflect
        接口 AnnotatedElement
所有已知实现类:
        AccessibleObject, Class, Constructor, Field, Method, Package

表示目前正在此 VM 中运行的程序的一个已注释元素。该接口允许反射性地读取注释。由此接口中的方法返回的所有注释都是不可变并且可序列化的。调用者可以修改已赋值数组枚举成员的访问器返回的数组;这不会对其他调用者返回的数组产生任何影响。

如果此接口中的方法返回的注释(直接或间接地)包含一个已赋值的 Class 成员,该成员引用了一个在此 VM 中不可访问的类,则试图通过在返回的注释上调用相关的类返回的方法来读取该类,将导致一个 TypeNotPresentException。

isAnnotationPresent
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)

如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。此方法主要是为了便于访问标记注释而设计的。

参数:

annotationClass - 对应于注释类型的 Class 对象

返回:

如果指定注释类型的注释存在于此对象上,则返回 true,否则返回 false

抛出:

NullPointerException - 如果给定的注释类为 null

从以下版本开始:

1.5

getAnnotation
<T extends Annotation> T getAnnotation(Class<T> annotationClass)

如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。

参数:

annotationClass - 对应于注释类型的 Class 对象

返回:

如果该元素的指定注释类型的注释存在于此对象上,则返回这些注释,否则返回 null

抛出:

NullPointerException - 如果给定的注释类为 null

从以下版本开始:

1.5

getAnnotations
Annotation[] getAnnotations()

返回此元素上存在的所有注释。(如果此元素没有注释,则返回长度为零的数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。

返回:

此元素上存在的所有注释

从以下版本开始:

1.5

getDeclaredAnnotations
Annotation[] getDeclaredAnnotations()

返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。

返回:

直接存在于此元素上的所有注释

从以下版本开始:

1.5


下面是使用反射读取RUNTIME保留策略的Annotation信息的例子:

自定义注解:

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {

    String[] value1() default "abc";
}

使用自定义注解:

public class AnnotationTest2 {

    @MyAnnotation(value1={"a","b"})
    @Deprecated
    public void execute(){
        System.out.println("method");
    }
}

读取注解中的信息:

public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    AnnotationTest2 annotationTest2 = new AnnotationTest2();
    //获取AnnotationTest2的Class实例
    Class<AnnotationTest2> c = AnnotationTest2.class;
    //获取需要处理的方法Method实例
    Method method = c.getMethod("execute", new Class[]{});
    //判断该方法是否包含MyAnnotation注解
    if(method.isAnnotationPresent(MyAnnotation.class)){
        //获取该方法的MyAnnotation注解实例
        MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
        //执行该方法
        method.invoke(annotationTest2, new Object[]{});
        //获取myAnnotation
        String[] value1 = myAnnotation.value1();
        System.out.println(value1[0]);
    }
    //获取方法上的所有注解
    Annotation[] annotations = method.getAnnotations();
    for(Annotation annotation : annotations){
        System.out.println(annotation);
    }
}
8、限定注解的使用:

限定注解使用@Target。

@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Target

指示注释类型所适用的程序元素的种类。如果注释类型声明中不存在 Target 元注释,则声明的类型可以用在任一程序元素上。如果存在这样的元注释,则编译器强制实施指定的使用限制。 例如,此元注释指示该声明类型是其自身,即元注释类型。它只能用在注释类型声明上:

@Target(ElementType.ANNOTATION_TYPE)
    public @interface MetaAnnotationType {
        ...
    }

此元注释指示该声明类型只可作为复杂注释类型声明中的成员类型使用。它不能直接用于注释:

@Target({}) 
    public @interface MemberType {
        ...
    }

这是一个编译时错误,它表明一个 ElementType 常量在 Target 注释中出现了不只一次。例如,以下元注释是非法的:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD})
    public @interface Bogus {
        ...
    }
public enum ElementType
extends Enum<ElementType>

程序元素类型。此枚举类型的常量提供了 Java 程序中声明的元素的简单分类。

这些常量与 Target 元注释类型一起使用,以指定在什么情况下使用注释类型是合法的。

ANNOTATION_TYPE
注释类型声明
CONSTRUCTOR
构造方法声明
FIELD
字段声明(包括枚举常量)
LOCAL_VARIABLE
局部变量声明
METHOD
方法声明
PACKAGE
包声明
PARAMETER
参数声明
TYPE
类、接口(包括注释类型)或枚举声明


注解的使用限定的例子:

@Target(ElementType.METHOD)
public @interface MyAnnotation {

    String[] value1() default "abc";
}
9、在帮助文档中加入注解:

要想在制作JavaDoc文件的同时将注解信息加入到API文件中,可以使用java.lang.annotation.Documented。

在自定义注解中声明构建注解文档:

@Documented
public @interface MyAnnotation {

    String[] value1() default "abc";
}

使用自定义注解:

public class AnnotationTest2 {

    @MyAnnotation(value1={"a","b"})
    public void execute(){
        System.out.println("method");
    }
}
10、在注解中使用继承:

默认情况下注解并不会被继承到子类中,可以在自定义注解时加上java.lang.annotation.Inherited注解声明使用继承。

@Documented
@Retention(value=RUNTIME)
@Target(value=ANNOTATION_TYPE)
public @interface Inherited

指示注释类型被自动继承。如果在注释类型声明中存在 Inherited 元注释,并且用户在某一类声明中查询该注释类型,同时该类声明中没有此类型的注释,则将在该类的超类中自动查询该注释类型。此过程会重复进行,直到找到此 类型的注释或到达了该类层次结构的顶层 (Object) 为止。如果没有超类具有该类型的注释,则查询将指示当前类没有这样的注释。

注意,如果使用注释类型注释类以外的任何事物,此元注释类型都是无效的。还要注意,此元注释仅促成从超类继承注释;对已实现接口的注释无效。

分享到:
评论

相关推荐

    Java学习基础笔记+代码注解

    Java学习基础笔记+代码注解是一份非常适合Java初学者的学习资料,它涵盖了Java语言的核心概念和基本语法,通过详尽的注解帮助理解代码逻辑。本文将深入解析这些知识点,帮助你快速掌握Java编程。 一、Java语言简介 ...

    Java 5 annotation 学习笔记

    Java 5引入的注解(Annotation)是一种元数据,它提供了在代码中嵌入信息的方式,这些信息可以被编译器、JVM或其他工具在编译时或运行时使用。注解可以用来简化代码,提高可维护性,并帮助工具进行静态分析。 1. ...

    学习Spring笔记_Annotation(注解)_Component

    本篇笔记主要关注Spring中的注解(Annotation)和@Component,这两大概念是Spring框架的重要组成部分,也是理解SpringIoC(控制反转)和AOP(面向切面编程)的基础。 首先,注解(Annotation)是Java提供的一种元...

    【Java基础笔记】枚举和注解.docx

    在Java编程语言中,枚举(Enum)和注解(Annotation)是两种非常重要的特性,它们分别用于定义固定的常量集合和提供元数据信息。以下是对这两个概念的详细说明: **一、枚举类** 1. **定义**: - 自定义枚举类:...

    java全套笔记 来自狂神说java笔录.zip

    10. **注解(Annotation)**:学习自定义注解和元注解,了解它们在代码中的应用,如Spring框架中的注解。 11. **Java IO/NIO**:深入理解流的分类,学习非阻塞I/O模型NIO(New Input/Output)。 12. **Java 8及更...

    Java基础尚硅谷宋红康学习笔记

    4. **注解(Annotation)**:注解提供了一种元数据,用于向编译器或JVM提供关于代码的附加信息,例如用于代码生成、编译时验证或运行时处理。 5. **集合框架高级**:包括List、Set、Map接口的高级实现,如TreeSet、...

    Hibernate Annotation 笔记 总结 注解

    【描述】:本文将全面介绍Hibernate Annotation的使用,包括事务管理和声明式事务处理,以及如何通过注解简化数据库持久化操作。 【标签】:Hibernate, Annotation, 笔记, 总结, 注解 【正文】: Hibernate ...

    龙哥的Java基础笔记大全

    这份笔记集合了Java编程语言的基础知识,旨在帮助读者从零开始掌握这门广泛使用的编程语言。以下是对笔记中涉及的主要知识点的详细阐述: 1. **Java简介**:Java是由Sun Microsystems公司开发的面向对象的编程语言...

    Java基础笔记_Java基础笔记_Java笔记_worthnwg_

    这份"Java基础笔记"涵盖了初学者需要掌握的关键知识点,旨在帮助快速入门Java编程。以下是对这些笔记内容的详细解读: 1. **Java简介**:Java是由Sun Microsystems(现已被Oracle公司收购)于1995年发布的面向对象...

    学习Spring笔记_Annotation(注解)_Autowired_Qualifier

    Spring的核心特性之一是使用注解来简化配置,其中`@Autowired`和`@Qualifier`是两个关键的注解,它们在自动装配Bean时发挥着重要作用。这篇学习Spring笔记将深入探讨这两个注解的用法、原理以及它们在实际开发中的...

    MLDN学习笔记 —— Annotation

    《MLDN学习笔记——Annotation》这篇博文主要探讨的是在编程领域中,特别是Java语言中,关于Annotation(注解)的深入理解和应用。Annotation是Java语言提供的一种元数据,它为程序提供了额外的信息,这些信息可以被...

    Java学习笔记适合java初学者使用

    11. **注解(Annotation)**:了解注解的使用和自定义注解的创建,及其在编译和运行时的作用。 在【Java试卷】部分,这些理论知识将通过各种题目进行检验,包括选择题、填空题和编程题。这些题目可能涵盖以上所有...

    java基础笔记.zip

    10. **枚举与注解**:学习Java中的枚举类型,以及注解(Annotation)的使用,包括自定义注解。 11. **泛型**:理解泛型的引入,以及在类、接口、方法中的应用,泛型通配符的使用。 12. **IO流新特性**:Java NIO...

    java基础知识笔记 java基础知识笔记

    在“CoreJava笔记.doc”中,可能包含了以上这些知识点的详细解释和实例代码,而“ReadMe.txt”可能是一个简单的引导文档,指示如何使用这些笔记或者提醒注意的要点。通过深入阅读和实践这些笔记,初学者可以建立起...

    java基础知识笔记

    14. **注解(Annotation)**:注解是元数据的一种形式,用于向编译器或JVM提供信息,如配置、编译时检查、运行时处理等。 15. **垃圾回收(Garbage Collection)**:Java自动进行内存管理,垃圾回收机制负责回收...

    java学习笔记

    这本书深入浅出地介绍了Java编程语言的基础知识和核心概念,旨在帮助读者快速掌握这一强大的开发工具。 首先,书中从Java的历史和发展背景出发,解释了为什么Java能够成为全球广泛应用的编程语言之一。接着,它引导...

    java笔记.zip

    尚硅谷康师傅java学习...2020-4-10 java 注解(Annotation) 2020-4-11 Java 集合 2020-4-15 java 泛型 2020-4-18 java IO流 2020-4-19 java 网络编程 2020-4-21 java反射 2020-4-22 java8 新特性 2020-4-27 单元测试

    java基础核心学习笔记

    本学习笔记将深入探讨Java的核心概念,帮助你建立坚实的基础。 1. **Java语法基础** - 变量与数据类型:Java支持基本数据类型(如int、float、char)以及引用数据类型(如类、接口、数组)。变量声明必须指定类型...

    java基础总结大全(笔记).pdf.zip

    这份"java基础总结大全(笔记).pdf"涵盖了Java的基础知识,对于学习者来说是一份宝贵的资源。 1. **Java语法基础**:Java的基础语法包括变量、数据类型、运算符、流程控制语句(如if条件语句、switch选择语句、for、...

Global site tag (gtag.js) - Google Analytics