Java注解Annotation与自定义注解详解

yizhihongxing

Java注解Annotation与自定义注解详解

概述

Java注解是在Java5中加入的新特性,是代码中的特殊标记,用于给类、方法、变量等元素添加附加信息,这些信息在编译、运行时处理或者是在代码分析的时候会被读取。注解可以看作是一种高级的Java注释,它与代码有紧密的联系。

Java注解可以分为三类:

  1. 预定义注解:JDK提供的注解,例如@Override@Deprecated@SuppressWarnings
  2. 元注解:用于自定义注解的注解,例如@Retention@Target@Documented
  3. 自定义注解:用户自己定义的注解,可以用@interface关键字定义。

预定义注解

@Override

指明某一个方法覆盖了父类的方法,如果父类中没有该方法,使用该注解会导致编译错误。

@override
public void foo() {
    // some code here
}

@Deprecated

标记一个方法或类已经弃用,不再推荐使用。

@Deprecated
public class OldClass {
    // some code here
}

@SuppressWarnings

指定一种或多种不显示任何编译器警告,这样可以防止出现不必要的编译警告。

@SuppressWarnings("unchecked")
List<String> list = new ArrayList();

元注解

@Retention

指定注解运行时生命周期。取值为RetentionPolicy中的枚举值,有三种可选:SOURCECLASSRUNTIME

  • SOURCE:只在源代码中存在,编译时就会被忽略。
  • CLASS:编译时被存储在class文件中,但是在运行时不会被JVM保留。
  • RUNTIME:运行时存在,可以通过反射获取注解信息。
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    // some code here
}

@Target

指定注解应用的目标类型,取值为ElementType中的枚举值,可以单独使用也可以组合使用。

@Target(ElementType.TYPE)
public @interface MyAnnotation {
    // some code here
}

@Documented

将注解包含在JavaDoc中。

@Documented
public @interface MyAnnotation {
    // some code here
}

自定义注解

自定义注解是使用@interface关键字定义的,它和定义Java类很像,可以定义元素,方法,抛出的异常等等。在使用自定义注解时,需要给注解元素设置值。下面给出一个简单的例子:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String value() default "";
    int id();
    String[] names();
}

该注解有三个元素:valueidnames,对应不同的数据类型,其中valueid均为必填,value默认值为""。下面给出一个使用该注解的例子:

@MyAnnotation(id=1, names={"abc", "def"})
public class Test {
    @MyAnnotation(id=2)
    public void foo() {
        // some code here
    }
}

示例说明

示例1:用自定义注解实现权限控制

定义一个注解@Permission,用于标注有权限限制的方法。同时编写一个PermissionHandler类,用于获取当前用户权限,并检查访问该方法所需的权限是否满足。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Permission {
    String[] value();
}

public class PermissionHandler {

    public static boolean hasPermission(String[] permissions) {
        // some code here
        return true;
    }

    public static boolean checkPermission(Method method) {
        boolean hasPermission = true;
        if (method.isAnnotationPresent(Permission.class)) {
            Permission permission = method.getAnnotation(Permission.class);
            hasPermission = hasPermission(permission.value());
        }
        return hasPermission;
    }
}

下面定义一个测试类,并在其中使用@Permission注解:

public class Test {

    @Permission({"read", "write"})
    public void foo() {
        System.out.println("do foo");
    }

    public void bar() {
        System.out.println("do bar");
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Test test = new Test();
        Method fooMethod = test.getClass().getMethod("foo");
        if (PermissionHandler.checkPermission(fooMethod)) {
            test.foo();
        }
        Method barMethod = test.getClass().getMethod("bar");
        if (PermissionHandler.checkPermission(barMethod)) {
            test.bar();
        }
    }
}

运行上述测试代码,当用户具备readwrite权限时,执行foo方法,否则不执行。

示例2:用注解生成文档

定义一个注解@Doc,用于标注需要生成文档的类和方法,同时编写一个DocGenerator类,用于生成文档。

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Doc {
    String desc();
    String author();
    String date();
}

public class DocGenerator {

    public static void generate(Class<?> clazz) {
        if (clazz.isAnnotationPresent(Doc.class)) {
            Doc classDoc = clazz.getAnnotation(Doc.class);
            System.out.println("Class: " + clazz.getSimpleName() + ":\n   " + classDoc.desc() +
                " By " + classDoc.author() + " On " + classDoc.date());
        }
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            if (method.isAnnotationPresent(Doc.class)) {
                Doc methodDoc = method.getAnnotation(Doc.class);
                System.out.println("Method: " + method.getName() + ":\n   " + methodDoc.desc() +
                    " By " + methodDoc.author() + " On " + methodDoc.date());
            }
        }
    }
}

下面定义一个测试类,并在其中使用@Doc注解:

@Doc(desc="This is a test class", author="John", date="2021-08-01")
public class Test {

    @Doc(desc="This is a test method", author="John", date="2021-08-02")
    public void foo() {
        System.out.println("do foo");
    }

    public static void main(String[] args) {
        DocGenerator.generate(Test.class);
    }
}

运行上述测试代码,将会生成如下的文档:

Class: Test:
   This is a test class By John On 2021-08-01
Method: foo:
   This is a test method By John On 2021-08-02

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java注解Annotation与自定义注解详解 - Python技术站

(0)
上一篇 2023年6月25日
下一篇 2023年6月25日

相关文章

  • iframe自适应高度的多种方法方法小结

    下面为您介绍一下“iframe自适应高度的多种方法方法小结”的完整攻略。 一、背景介绍 在网页中,不同的网站可能会有不同的需求。有时候,我们可能需要在网页中嵌入一个其他网站提供的页面,这时就需要使用iframe标签。但是,iframe标签默认高度为固定值,如何实现自适应高度呢?下面我们来看看一些常见的方法。 二、方法一:使用jQuery 在网页中,可以使用j…

    other 2023年6月26日
    00
  • 快速构建Windows 8风格应用1-开发工具安装及模拟器使用

    快速构建Windows 8风格应用1-开发工具安装及模拟器使用攻略 本文将详细介绍如何快速构建Windows 8风格应用,包括开发工具的安装和模拟器的使用。本文将提供两个示例说明。 开发工具安装 在构建Windows 8风格应用之前,需要安装Visual Studio 2012或更高版本的开发工具。以下是安装步骤: 下载Visual Studio 2012或…

    other 2023年5月5日
    00
  • Perl脚本实现递归遍历目录下的文件

    下面是Perl脚本实现递归遍历目录下的文件的完整攻略,包括基本概念、实现递归遍历的技巧和示例说明。 基本概念 在编写Perl脚本实现递归遍历目录下的文件时,需要掌握以下基本概念: 目录:指在计算机保存文件和文件夹的容器,是文件系统的核心部分。 文件:指计算机中的数据存储单位,是一段被命名的存储区域。 递归:指在程序执行过程中,自己调用自己的过程。 实现递归遍…

    other 2023年6月27日
    00
  • mac怎么开启nfs共享

    Mac如何开启NFS共享 NFS(Network File System)是一种用来在网络中共享文件系统资源的协议。在Mac上,我们可以使用NFS共享文件夹和文件,以便在局域网内的其他Mac或Linux系统上访问和使用。 下面是如何在Mac上启用NFS共享的步骤。 步骤1:打开终端 要启用NFS共享,我们需要在终端中执行一些命令。在Mac上打开终端的方法有很…

    其他 2023年3月28日
    00
  • Windows系统环境变量大全 举例说明(XP/Win7/Win8)

    Windows系统环境变量大全 举例说明(XP/Win7/Win8) 什么是环境变量 环境变量是指在操作系统中预先设定好的一些参数,用于存储与操作系统有关的信息,如系统路径、JAVA_HOME等。我们可以通过修改环境变量来实现对系统参数的修改。 环境变量的类型 Windows系统环境变量可以分为用户环境变量和系统环境变量。 用户环境变量 用户环境变量属于当前…

    other 2023年6月27日
    00
  • base64之js压缩图片

    base64之js压缩图片 在Web开发中,图像文件传输占据了极大的带宽。为此,我们可以使用一些方法来减少图像传输的大小。其中,将图像压缩为base64编码字符串并将其添加到HTML或CSS文件中是一种常见的方法。在这篇文章中,我们将学习如何使用JavaScript对图像进行压缩,并将其转换为base64编码字符串以缩小文件的大小。 为什么要使用base64…

    其他 2023年3月28日
    00
  • vivo X Fold2开发者模式在哪 vivo X Fold2进入开发者模式的方法

    以下是“vivo X Fold2开发者模式在哪 vivo X Fold2进入开发者模式的方法”的完整攻略: 一、vivo X Fold2开发者模式在哪 要在vivo X Fold2中找到开发者模式,可以按照以下步骤进行操作: 打开设置应用。可以通过点击主屏幕上的“设置”图标或从通知栏中下拉通知栏,然后点击“设置”来打开设置应用。 向下滑动屏幕,找到“关于手机…

    other 2023年6月26日
    00
  • iOS获取手机ip地址代码

    获取iOS设备的IP地址可以使用以下代码: import Foundation import Network func getIPAddress() -> String? { var ipAddress: String? let monitor = NWPathMonitor() let queue = DispatchQueue(label: \&q…

    other 2023年7月30日
    00
合作推广
合作推广
分享本页
返回顶部