JavaSE—注解(1)

1 注解的定义和作用

注解与注释:

注解:告诉编译器如何运行程序!

注释: 给程序员阅读,对编译、运行没有影响;

注解作用

  1. 告诉编译器如何运行程序;

  2. 简化(取代)配置文件

// 重写父类的方法
@Override
public String toString() {
    return super.toString();
}

// 抑制编译器警告 List不加泛型会出警告
@SuppressWarnings({"unused","unchecked"})
private void save() {
    List list = null;
}

// 标记方法以及过时
@Deprecated
private void save1() {
}

2 自定义注解

通过自定义注解,可以给类、字段、方法上添加描述信息!

2.1 元注解

元注解,表示注解的注解!

  1. 指定注解的可用范围:
@Target({
    TYPE,FIELD,    	  字段
    METHOD,  	  方法
    PARAMETER,    参数
    CONSTRUCTOR,  构造器
    LOCAL_VARIABLE  局部变量
})
  1. 指定注解的生命周期
@Retention(RetentionPolicy.SOURCE)    注解只在源码级别有效
@Retention(RetentionPolicy.CLASS)     注解在字节码级别有效  默认值
@Retention(RetentionPolicy.RUNTIME)   注解在运行时期有效

2.2 案例

//表示这个注解可以作用到方法、属性、类上
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Author {
    
    String name() default "";
    
    //带默认值的属性,使用时候不给这个属性赋值,也有一个默认值
    int age() default 20;

    //如果使用注解里面的value属性,使用的时候可以省略.
    //前提是:注解中只有这一个属性时候
    String[] value() default {};
}

//@Author("男")
//@Author(value = "男")
//@Author(value = {"男", "女"})
@Author(name = "zhao", age = 12, value = "男")
public class AuthorDemo {

    @Author
    private String str;

    @Author(name = "zhangsan", age = 23, value = {"男", "女"})
    //@Author(name = "zhangsan")
    public void add() {
    }

    @Test
    public void test1() throws NoSuchMethodException {
        Class<AuthorDemo> clazz = AuthorDemo.class;
        Author typeAuthor = clazz.getAnnotation(Author.class);
        System.out.println(typeAuthor.value()[0]);

        //1.先获得代表这个方法的Method
        Method method = clazz.getDeclaredMethod("add");
        //2.在Method上拿到指定注解
        Author methodAnnotation = method.getAnnotation(Author.class);
        System.out.println(methodAnnotation.name());//zhangsan
        System.out.println(methodAnnotation.age());//23
        System.out.println(Arrays.toString(methodAnnotation.value()));//[男, 女]
    }
}

3 解释一下

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Author {

    String[] value() default {};
}

这是一个 Java 注解的定义。注解是 Java 中的一种元数据,可以附加到代码中的类、方法、字段等元素上,用于提供额外的信息。让我们详细解释这个注解的各个部分。

注解定义

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Author {

    String[] value() default {};
}

详细解释

  1. @Target 注解(元注解)

    • @Target 注解指定了这个自定义注解可以应用的目标。
    • 在这里,@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE}) 表示这个注解可以应用于方法、字段和类(类型)。
    • ElementType 的常见类型包括:
      • ElementType.METHOD:方法
      • ElementType.FIELD:字段
      • ElementType.TYPE:类、接口(包括注解类型)或枚举声明
  2. @Retention 注解(元注解)

    • @Retention 注解指定了这个自定义注解的保留策略。
    • 在这里,@Retention(RetentionPolicy.RUNTIME) 表示这个注解在运行时可见。这意味着可以使用反射机制在运行时读取这个注解。
    • RetentionPolicy 的常见类型包括:
      • RetentionPolicy.SOURCE:注解只在源码中存在,编译时会被丢弃。
      • RetentionPolicy.CLASS:注解在编译时会被保留在类文件中,但在运行时不会被保留。
      • RetentionPolicy.RUNTIME:注解在运行时保留,可以通过反射机制读取。
  3. 注解的定义

    • public @interface Author:这是定义一个名为 Author 的注解。
    • String[] value() default {};:定义了一个名为 value 的属性,它是一个 String 数组,默认值是一个空数组。
      • 在使用这个注解时,可以提供一个或多个字符串值。例如:@Author({"Alice", "Bob"})@Author("Alice")

示例使用

应用在类上
@Author("Alice")
public class MyClass {
    // 类代码
}
应用在方法上
public class MyClass {
    @Author({"Alice", "Bob"})
    public void myMethod() {
        // 方法代码
    }
}
应用在字段上
public class MyClass {
    @Author("Charlie")
    private String myField;
}

读取注解

//如果指定类型的注解存在于此元素上,方法返回true,否则返回false。
A.isAnnotationPresent(B.class)
//B类型的注解是否存在于A元素(可以是类、字段(属性)、方法)上

通过反射可以读取这些注解的信息。例如:

import java.lang.reflect.Method;

public class AnnotationReader {
    public static void main(String[] args) throws Exception {
        // 获取类上的注解
        Class<MyClass> clazz = MyClass.class;
        if (clazz.isAnnotationPresent(Author.class)) {
            Author author = clazz.getAnnotation(Author.class);
            System.out.println("Class Author: " + String.join(", ", author.value()));
        }

        // 获取方法上的注解
        Method method = clazz.getMethod("myMethod");
        if (method.isAnnotationPresent(Author.class)) {
            Author author = method.getAnnotation(Author.class);
            System.out.println("Method Author: " + String.join(", ", author.value()));
        }

        // 获取字段上的注解
        Field field = clazz.getDeclaredField("myField");
        if (field.isAnnotationPresent(Author.class)) {
            Author author = field.getAnnotation(Author.class);
            System.out.println("Field Author: " + String.join(", ", author.value()));
        }
    }
}

总结

这个注解定义了一个名为 Author 的自定义注解,可以应用于类、方法和字段。通过 @Target 注解指定了可以应用的目标,通过 @Retention 注解指定了它的保留策略为运行时,并定义了一个 String 数组类型的 value 属性。这个注解可以在源码中提供作者信息,并在运行时通过反射机制读取。

4 如果使用时只用@Author会发生什么

如果在使用 @Author 注解时只写 @Author 而不提供任何参数,根据注解的定义,注解的 value 属性将使用默认值。因为 value 属性的默认值是一个空数组 default {},所以这相当于没有指定任何作者信息。

注解的默认值

在注解的定义中,String[] value() default {}; 表示 value 属性有一个默认值,即一个空的 String 数组。如果使用注解时不提供任何参数,value 属性将使用这个默认值。

示例使用

仅使用 @Author 注解
@Author
public class MyClass {
    // 类代码
}
使用反射读取注解

通过反射读取注解时,如果没有提供任何参数,value 属性将是一个空数组。

import java.lang.reflect.Method;

public class AnnotationReader {
    public static void main(String[] args) throws Exception {
        // 获取类上的注解
        Class<MyClass> clazz = MyClass.class;
        if (clazz.isAnnotationPresent(Author.class)) {
            Author author = clazz.getAnnotation(Author.class);
            System.out.println("Class Author: " + String.join(", ", author.value()));
        }

        // 获取方法上的注解
        Method method = clazz.getMethod("myMethod");
        if (method.isAnnotationPresent(Author.class)) {
            Author author = method.getAnnotation(Author.class);
            System.out.println("Method Author: " + String.join(", ", author.value()));
        }

        // 获取字段上的注解
        Field field = clazz.getDeclaredField("myField");
        if (field.isAnnotationPresent(Author.class)) {
            Author author = field.getAnnotation(Author.class);
            System.out.println("Field Author: " + String.join(", ", author.value()));
        }
    }
}

输出结果

如果 @Author 注解没有提供任何参数,读取到的 value 属性将是一个空数组,因此输出将为空。

示例类
@Author
public class MyClass {
    @Author
    private String myField;

    @Author
    public void myMethod() {
        // 方法代码
    }
}
示例输出
Class Author: 
Method Author: 
Field Author: 

总结

当你使用 @Author 注解而不提供任何参数时,注解的 value 属性将使用其默认值(即一个空数组)。读取这个注解时,会发现 value 属性是空的,表示没有指定任何作者信息。这是因为 String[] value() default {} 定义了 value 属性的默认值为一个空数组。

5 不提供参数的注解有啥用?

注解在 Java 中的作用取决于它们如何被设计和使用。虽然在某些情况下,不提供参数的注解(例如 @Author 没有参数)可能看起来没有明显的用途,但它们仍然可以在特定的上下文中有意义。以下是一些可能的用途和设计意图:

1. 标记用途

不带参数的注解可以用作简单的标记,用来标记某些元素(类、方法、字段等)具有特定的特性或需要特定的处理。

示例
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Important {
    // 这个注解没有参数,仅用于标记
}

在使用时:

@Important
public class MyClass {
    @Important
    private String importantField;

    @Important
    public void importantMethod() {
        // 重要的方法
    }
}

2. 反射处理

在运行时,通过反射来检查和处理这些标记注解。例如,可以在框架或库中使用这些注解来执行特定的逻辑。

示例:反射处理标记注解
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class AnnotationProcessor {
    public static void main(String[] args) throws Exception {
        Class<MyClass> clazz = MyClass.class;

        if (clazz.isAnnotationPresent(Important.class)) {
            System.out.println("Class " + clazz.getName() + " is important.");
        }

        for (Field field : clazz.getDeclaredFields()) {
            if (field.isAnnotationPresent(Important.class)) {
                System.out.println("Field " + field.getName() + " is important.");
            }
        }

        for (Method method : clazz.getDeclaredMethods()) {
            if (method.isAnnotationPresent(Important.class)) {
                System.out.println("Method " + method.getName() + " is important.");
            }
        }
    }
}

3. 兼容性和扩展性

设计注解时允许有参数和无参数两种形式,可以增强注解的灵活性和兼容性。在需要详细信息时可以传递参数,而在不需要详细信息时可以仅使用标记。

示例
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Author {
    String[] value() default {};
}

// 使用时可以只作为标记
@Author
public class MyClass {
    // 或者提供具体的值
    @Author({"Alice", "Bob"})
    private String importantField;

    @Author("Charlie")
    public void importantMethod() {
        // 重要的方法
    }
}

4. 默认值的意义

即使是默认值为空,注解仍可以提供关于代码结构的信息,并且允许将来扩展。例如,可以在后续开发中引入新的处理逻辑或使用策略,而不需要修改现有的代码。

总结

虽然不带参数的 @Author 注解在看起来可能没有直接的作用,但它仍可以用于标记、反射处理、提供兼容性和扩展性等用途。实际的用处取决于开发者如何设计和使用这些注解。在实际开发中,注解的使用往往是为了提供元数据,标记特定特性,并在运行时进行处理或执行特定的逻辑。

  • 36
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值