Java之注解Annotation

Java 注解(Annotation)是 JDK 5.0 引入的一种元数据机制,用于描述某些代码的附加信息,这些信息可以在运行时或编译时被读取。注解本身不会改变程序的执行流程,但可以被编译器或运行时环境用来进行额外的处理。

注解的定义

Java 注解使用 @interface 关键字来定义,例如:

public @interface TestInterface {
    String value() default "默认注解";
}

注解的应用

注解可以应用于类、方法、成员变量、参数、构造器和包等元素上,为这些元素附加某种元数据。

@TestInterface("这是一个注解示例") 
public class Test {
    //.....
}

内置注解

Java 提供了几个内置注解,如 @Override@Deprecated 和 @SuppressWarnings

  • @Override:表示一个方法是重写了父类或是实现了接口中的一个方法。
  • @Deprecated:表示某个类或方法已经过时,不建议使用。
  • @SuppressWarnings:告诉编译器忽略特定的警告信息。
元注解

元注解是用于描述注解的注解,Java 定义了 4 个标准的 meta-annotation 类型,它们被用来提供对其它 annotation 类型作注解。这些类型和它们所支持的类在 java.lang.annotation 包中可以找到。

  • @Target: 表示该注解可以用于什么地方。可能的 ElementType 参数包括:
    • CONSTRUCTOR: 构造器的声明
    • FIELD: 域声明(包括枚举的常量)
    • LOCAL_VARIABLE: 局部变量声明
    • METHOD: 方法声明
    • PACKAGE: 包声明
    • PARAMETER: 参数声明
    • TYPE: 类、接口(包括注解类型)或枚举的声明
  • @Retention: 表示需要在什么级别保存该注解信息,用于描述注解的生命周期(SOURCE < CLASS < RUNTIME)。
  • @Documented: 将此注解包含在 javadoc 中。
  • @Inherited: 允许子类继承父类的注解。
自定义注解

你可以根据需要创建自定义注解,并定义注解的元素和默认值等。例如:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@TestInterface  //写在在这会报错,因为这个注解限定只能用在方法上
public class Test {
    
    @TestInterface
    public String testInterface (){
        return "";
    }
    //.....
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface TestInterface {
    String value() default "默认注解";
}
自定义注解的一些特殊使用

特殊语法一:

如果注解本身没有注解类型元素,那么在使用注解的时候可以省略(),直接写为:@注解名,它和标准语法@注解名()等效!

@TestInterface  
public class Test {
}

@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.TYPE})
@interface TestInterface {
}

特殊语法二:

如果注解本本身只有一个注解类型元素,而且命名为value,那么在使用注解的时候可以直接使用:@注解名(注解值),其等效于:@注解名(value = 注解值)。

@TestInterface(name = "这个一个注解")
public class Test {
}

@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.TYPE})
@interface TestInterface {
    String[] name();
}

特殊用法三:

如果注解中的某个注解类型元素是一个数组类型,在使用时又出现只需要填入一个值的情况,那么在使用注解时可以直接写为:@注解名(类型名 = 类型值),它和标准写法:@注解名(类型名 = {类型值})等效!

@TestInterface(name = "这个一个注解")
public class Test {
}

@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.TYPE})
@interface TestInterface {
    String[] name();
}

@TestInterface(name = {"第一个值","第二个值"})
class TestArrayInterface  {
}

特殊用法四:

如果一个注解的@Target是定义为Element.PACKAGE,那么这个注解是配置在package-info.java中的,而不能直接在某个类的package代码上面配置。

注:package-info.java 提供包级别的类(或接口),这些类(或接口)只有本包里才能访问,即使是子包也不能访

自定义注解的使用例子:
/**
 * @author: Admin
 * @Desc: 测试自定注解类
 * @create: 2024-08-02 16:54
 **/
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.TYPE})
public @interface TestInterface {
    String name() default "默认值";

    int age() default 18;

    String hobbies() default "篮球";

    String address() default "北京";
}
/**
 * @author: Admin
 * @Desc: 测试自定注解类实体类
 * @Date: 2024/8/5 14:14
 */
public class Person {
    String name;
    int age;
    String address;
    String hobbies;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getHobbies() {
        return hobbies;
    }

    public void setHobbies(String hobbies) {
        this.hobbies = hobbies;
    }
}
/**
 * @author: Admin
 * @Desc: 测试自定注解类业务类
 * @Date: 2024/8/5 14:14
 */
public class TestService {
    @TestInterface(name = "张三", age = 22, address = "广州", hobbies = "足球")
    public void writeInfo(Person person) {
        String info = String.format("姓名:%s,年龄:%d,地址:%s,爱好:%s", person.getName(), person.getAge(), person.getAddress(), person.getHobbies());
        System.out.println(info);
    }
}
/**
 * @author: Admin
 * @Desc: 测试类
 * @create: 2024-08-02 16:54
 **/
public class Test {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class clazz = TestService.class;
        Method method = clazz.getMethod("writeInfo",Person.class);
        if (!method.isAnnotationPresent(TestInterface.class)) {
            System.out.printf("没有注解");
            return;
        }
        TestInterface info = method.getAnnotation(TestInterface.class);
        Person person = new Person();
        person.setName(info.name());
        person.setAge(info.age());
        person.setAddress(info.address());
        person.setHobbies(Arrays.asList(info.hobbies()).toString());
        TestService testService = new TestService();
        method.invoke(testService, person);

    }
}

执行结果:
姓名:张三,年龄:22,地址:广州,爱好:[足球]

注解的使用场景
1.编译时注解:

代码生成:注解可以用于生成额外的代码,例如,通过Lombok库自动生成getter和setter方法。

配置IDE:注解可以提供IDE特定的信息,如重构、代码分析等。

2.运行时注解:

依赖注入:在Spring框架中,注解如@Autowired用于自动装配依赖项。

数据验证:使用JSR 380(Bean Validation 2.0)注解,如@NotNull和@Size在运行时验证对象状态。

3.设计时注解:

API文档:如Javadoc注解,用于生成API文档。

框架配置:许多框架使用注解来配置框架行为,如Spring的@Controller、@Service等。

4.测试注解:

测试框架:JUnit等测试框架使用注解如@Test、@Before、@After来标记测试方法和测试生命周期方法。

5.序列化与反序列化:

JSON处理:Jackson和Gson等库使用注解来控制JSON的序列化和反序列化行为。

6.事务管理:

声明式事务:在Spring框架中,使用@Transactional注解来声明事务的边界和行为。

7.安全性:

权限控制:Spring Security等安全框架使用注解如@Secured、@RolesAllowed来控制访问权限。

8.性能监控:

方法执行时间:使用注解来标记需要监控的方法,然后通过特定的工具来测量其执行时间。

9.模块化和插件系统:

扩展点:框架或应用程序可以定义注解作为扩展点,允许第三方模块通过注解来注册它们的组件。

10.构建工具配置:

Maven和Gradle:这些构建工具使用注解来定义项目的配置和依赖关系。

11.RESTful Web服务:

路由和控制器:在使用Spring MVC或JAX-RS等框架时,注解用于定义路由和控制器方法。

12.数据库访问:

ORM框架:Hibernate和MyBatis等ORM框架使用注解来映射Java类到数据库表。

13.自定义注解:

特定业务逻辑:开发者可以创建自定义注解来标记特定的业务逻辑或代码段,然后在运行时通过反射进行处理。

  • 20
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值