⛳ Java注解

⛳ Java注解

  • 从 JDK 5.0 开始, Java 增加了对元数据(MetaData) 的支持, 也就是Annotation(注解)
  • Annotation 其实就是代码里的特殊标记, 这些标记可以在编译, 类加载, 运行时被读取, 并执行相应的处理。通过使用 Annotation, 程序员可以在不改变原有逻辑的情况下, 在源文件中嵌入一些补充信息。 代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证或者进行部署。
  • Annotation 可以像修饰符一样被使用, 可用于修饰包,类, 构造器, 方法, 成员变量, 参数, 局部变量的声明, 这些信息被保存在Annotation的 “name=value” 对中。
  • 在JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE/Android中注解占据了更重要的角色,例如用来配置应用程序的任何切面, 代替JavaEE旧版中所遗留的繁冗代码和XML配置等。
  • 未来的开发模式都是基于注解的, JPA是基于注解的, Spring2.5以上都是基于注解的, Hibernate3.x以后也是基于注解的,现在的Struts2有一部分也是基于注解的了,注解是一种趋势,一定程度上可以说: 框架 = 注解 + 反射 + 设计模式
  • 使用 Annotation 时要在其前面增加 @ 符号, 并把该 Annotation 当成一个修饰符使用。 用于修饰它支持的程序元素

🏭 一,常见的注解

  • @Override: 限定重写父类方法, 该注解只能用于方法
  • @Deprecated: 用于表示所修饰的元素(类, 方法等)已过时。通常是因为所修饰的结构危险或存在更好的选择
  • @SuppressWarnings: 抑制编译器警告
public class AnnotationTest{
     public static void main(String[] args) {
         @SuppressWarnings("unused")
         int a = 10;
     }
     @Deprecated
     public void print(){
         System.out.println("过时的方法");
     }
     @Override
     public String toString() {
         return "重写的toString方法()";
     }
 }

🎨 二,JDK元注解

  • JDK 的元 Annotation 用于修饰其他 Annotation 定义

  • JDK5.0提供了4个标准的meta-annotation类型, 分别是:

    • Retention (保持,保留)
    • Target (目标,指标)
    • Documented (备有证明文件的)
    • Inherited (遗传的;继承)
  • @Retention: 只能用于修饰一个 Annotation 定义, 用于指定该 Annotation 的生命周期, @Rentention 包含一个 RetentionPolicy 类型的成员变量, 使用@Retention 时必须为该 value 成员变量指定值:

    • RetentionPolicy.SOURCE:在源文件中有效(即源文件保留) , 编译器直接丢弃这种策略的注释
    • RetentionPolicy.CLASS:在class文件中有效(即class保留) , 当运行 Java 程序时, JVM不会保留注解。 这是默认值
    • RetentionPolicy.RUNTIME:在运行时有效(即运行时保留) , 当运行 Java 程序时, JVM 会保留注释。程序可以通过反射获取该注释。
  • @Target: 用于修饰 Annotation 定义, 用于指定被修饰的 Annotation 能用于修饰哪些程序元素。 @Target 也包含一个名为 value 的成员变量。

  • JDK1.8@Target新增类型如下:

    • ElementType.TYPE_PARAMETER 表示该注解能写在类型变量的声明语句中(如: 泛型声明) 。
    • ElementType.TYPE_USE 表示该注解能写在使用类型的任何语句中。
  • Java 8新增可重复注解:

  • @Documented: 用于指定被该元 Annotation 修饰的 Annotation 类将被javadoc 工具提取成文档。 默认情况下, javadoc是不包括注解的。

    • 定义为Documented的注解必须设置Retention值为RUNTIME。
  • @Inherited: 被它修饰的 Annotation 将具有继承性。如果某个类使用了被@Inherited 修饰的 Annotation, 则其子类将自动具有该注解。

    • 比如:如果把标有@Inherited注解的自定义的注解标注在类级别上,子类则可以继承父类类级别的注解

🚜 三,通过反射获取注解

  • JDK 5.0 在 java.lang.reflect 包下新增了 AnnotatedElement 接口, 该接口代表程序中可以接受注解的程序元素

  • 当一个 Annotation 类型被定义为运行时 Annotation 后, 该注解才是运行时可见, 当 class 文件被载入时保存在 class 文件中的 Annotation 才会被虚拟机读取

  • 程序可以调用 AnnotatedElement对象的如下方法来访问 Annotation 信息

    image-20230807102228960

🐾 3.1、JDK常用注解

Person:

package org.example.a_often_annotation;

public class Parent {


    @SuppressWarnings("unused")  // 抑制编译器警告
    public void f1(){
        System.out.println("parent f1");
    }

    @Deprecated   // 用于表示所修饰的元素(类,方法等)已过时。通常是因为所修饰的结构危险或者存在了更好的选择
    public void  f2(){
        System.out.println("parent f2");
    }


    public static void main(String[] args) {
        @SuppressWarnings("unused")
        int i = 123;

        Children children = new Children();
        children.f1();
        children.f2();

    }

}

children:

package org.example.a_often_annotation;

public class Children extends Parent{

    @Override
    public void f1() {
        System.out.println("children f1");
    }

    @Override
    public void f2() {
        System.out.println("children f2");
    }

    @Override
    public String toString() {
        return "Children{}";
    }
}

👣 3.2、简单注解

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

}

使用注解:

package org.example.b_simple_annotation;

public class Person {

    @MyAnnotation
    private String name;

    @MyAnnotation
    private int age;

    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;
    }

    @MyAnnotation
    public void show(){
        System.out.println("person -> show");
    }

    @MyAnnotation
    public void display(){
        System.out.println("person -> display");
    }
}

测试:

package org.example.b_simple_annotation;

import org.junit.Test;

import java.lang.reflect.Method;

public class TestAnnotation {

    /**
     *  反射调用类中的方法
     */
    @Test
    public void test1(){
        try {
            Class<?> personClass = Class.forName("org.example.b_simple_annotation.Person");
            Object personBean = personClass.newInstance();// 创建处一个person类的实例
            Method show = personClass.getMethod("show");
            show.invoke(personBean);  // 调用反射方法
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 注解调用方法
     */
    @Test
    public void test2(){
        try {
            Class<?> personClass = Class.forName("org.example.b_simple_annotation.Person");
            Object personBean = personClass.newInstance();// 创建处一个person类的实例

            // 方法有注解@MyAnnotation执行,没有的不执行
            Method[] methods = personClass.getMethods(); // 得到所有的方法
            for (int i = 0; i < methods.length; i++) {
                if(methods[i].isAnnotationPresent(MyAnnotation.class)){
                    methods[i].invoke(personBean);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

📢 3.3、复杂注解

注解:

package org.example.c_complex_annotation;

import java.lang.annotation.*;

@Inherited  // 表示如果有类使用该注解,这个类的所有子类也自动继承该注解
@Repeatable(MyAnnotations.class)   // 表示该注解在一个地方可以重复出现,实际上是多个该注解合成一个MyAnnotations注解
@Retention(RetentionPolicy.RUNTIME)   // 用于指定该 Annotation 的生命周期,runtime表示运行时保留
@Target({ElementType.FIELD,ElementType.METHOD})
public @interface ComplexAnnotation {

    String value() default "value的初始值";

}



package org.example.c_complex_annotation;

import java.lang.annotation.*;

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

}



package org.example.c_complex_annotation;


import java.lang.annotation.*;

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

    ComplexAnnotation[] value();

}

用例:

package org.example.c_complex_annotation;

public class CPerson {

    private String name;

    private int age;


    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;
    }

    @ComplexAnnotation(value = "hello show")
    public void show(){
        System.out.println("CPerson -> show");
    }

    @ComplexAnnotation
    public void display(){
        System.out.println("CPerson -> display");
    }

//    @MyAnnotations({@ComplexAnnotation("hello f2-1"),@ComplexAnnotation("hello f2-2")})  // 等价于下面两个@ComplexAnnotation注解
    @ComplexAnnotation("hello f2-1")
    @ComplexAnnotation("hello f2-2")
    @ComplexAnnotation2
    public void f2(){
        System.out.println("CPerson -> f2");
    }
}

测试:

package org.example.c_complex_annotation;

import org.junit.Test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

public class CTestAnnotation {

    @Test
    public void test1(){
        try {
            Class<?> personClass = Class.forName("org.example.c_complex_annotation.CPerson");
            Object personBean = personClass.newInstance();// 创建处一个person类的实例
            Method show = personClass.getMethod("show");
            show.invoke(personBean);  // 调用反射方法  结果:CPerson -> show
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     *  得到方法上的所有注解
     */
    @Test
    public void test2(){
        try {
            Class<?> personClass = Class.forName("org.example.c_complex_annotation.CPerson");
            Object personBean = personClass.newInstance();// 创建处一个person类的实例
            Method f2 = personClass.getMethod("f2");
            Annotation[] annotations = f2.getAnnotations();
            for (int i = 0; i < annotations.length; i++) {
                System.out.println(annotations[i]);
                /**
                 *  结果:
                 *      @org.example.c_complex_annotation.MyAnnotations(value=[@org.example.c_complex_annotation.ComplexAnnotation(value=hello f2-1), @org.example.c_complex_annotation.ComplexAnnotation(value=hello f2-2)])
                 *      @org.example.c_complex_annotation.ComplexAnnotation2()
                 */
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 得到方法上的特定注解的值
     */
    @Test
    public void test3(){
        try {
            Class<?> personClass = Class.forName("org.example.c_complex_annotation.CPerson");
            Object personBean = personClass.newInstance();// 创建处一个person类的实例
            Method show = personClass.getMethod("show");
            ComplexAnnotation annotation = show.getAnnotation(ComplexAnnotation.class);
            System.out.println(annotation.value());  // 结果:hello show
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 得到方法上的特定注解的值
     */
    @Test
    public void test4(){
        try {
            Class<?> personClass = Class.forName("org.example.c_complex_annotation.CPerson");
            Object personBean = personClass.newInstance();// 创建处一个person类的实例
            Method display = personClass.getMethod("display");
            ComplexAnnotation annotation = display.getAnnotation(ComplexAnnotation.class);
            System.out.println(annotation.value());  // 结果:value的初始值
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值