java之注解——我知道的java注解知识全都告诉你

什么是注解

网上java注解描述:Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。
Java 语言中的类、方法、变量、参数和包等都可以被标注。和 Javadoc 不同,Java 标注可以通过反射获取标注内容。
在编译器生成类文件时,标注可以被嵌入到字节码中。Java 虚拟机可以保留标注内容,在运行时可以获取到标注内容 。
当然它也支持自定义 Java 标注。

提取重点一下

1、JDK1.5 之后的新特性
2、用来说明程序的、
3、是元数据
4、使用注解:@注解名称(参数)

作用

有三种:
1、编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override】
2、编写文档:通过代码里标识的注解生成文档【生成文档doc文档】,API文档是通过抽取代码中的文档注释生成的。
3、代码分析:通过代码里标识的注解对代码进行分析【使用方式】(重点说明)

JDK中预定义的一些注解

@Override : 检测被该注解标注的方法是否搜集继承自父类(接口)的

@Deprecated :将该注解标注的内容,表示已过时

@SuppressWarnings :压制警告,一般传递参数all @SuppressWarnings(“all”)
在编码中最常见的就是 @Override、 @Deprecated

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

使用

使用的话我相信大家不陌生吧,开发中大大小小的框架都有使用注解的模式,注解在java开发中是日常可见。他们是如何实现相关功能的呢,我们从一个自定义注解说起。

自定义注解

我们先了解注解的张什么样子,已@Override为剖析点

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

分成两部分,先说接口部分

元注解
public @interface Override {
属性
}

其实使用了@interface,我们依葫芦画瓢

public @interface MyAnno {
}

这个是什么呢,根据@interface,推测注解是特殊接口
我们可以先对文件javac编译后再javap反编译看看其结构如何

public interface MyAnno extends java.lang.annotation.Annotation{
 
}
确定其本质是接口

属性

接口的话就有抽象方法,我们把其中的抽象方法称为属性
1.属性的返回值类型只能为以下几种:

基本数据类型
String
枚举
注解
以上类型的数组

  1. 定义了的属性(本质上是抽象方法),在使用时需要进行赋值

如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值。
如果只有一个属性需要赋值,并且这个属性的名称是value,那么value可以省略,直接赋值即可。

public @interface MyAnno {
   int value;
}

@MyAnno(1)
public class Test(){
}
数组赋值时,值使用大括号包裹。如果数组中只有一个值,那么{}可以省略。
public @interface MyAnno {
    int age();

    String name() default "小可爱";

    MyAnno2 anno2();

    String[] str();

}

@MyAnno(age = 1,name="小伙子",anno2 = @MyAnno,str = "1324")

在这里插入图片描述
第二部分:

元注解

概念:用于描述注解的注解。

@Target:描述能够作用的位置

@Target(value = {ElementType.TYPE}) //表示该MyAnno注解只能作用于类上
public @interface MyAnno {
}
其中value中ElementType取值可以有以下几种情况:

TYPE:可以作用在类上
METHOD:可以作用在方法上
FIELD:可以作用于成员变量上

 @Target(value = {ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
  public @interface MyAnno {
 }

表示该MyAnno注解可以同时作用于类上,方法上和成员变量上

@Retention:描述注解被保留的阶段

java三个运行阶段,SOURCE、CLASS、RUNTIME
@Retention(RetentionPolicy.RUNTIME):当前被描述的注解,会保留到字节码文件中,并被JVM读取到,一般自己定义的注解都加RUNTIME

@Documented:描述该注解是否会被抽取到api文档中

@Inherited:描述注解是否被子类继承

注解一般是用来处理配置

可以在注解属性中加入配置信息,如
SpringBoot中
在这里插入图片描述
在这里插入图片描述
也可以在类中获取注解设置的属性

@Target(ElementType.TYPE) //可以被作用在类上
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnoReflect {
    String className();
    String methodName();


@AnnoReflect(className = "cn.other.annotation.AnnoTest1",methodName = "play")
public class ReflectAnnotationTest {
    public static void main(String[] args) throws Exception {

 //1. 解析注解
        //1.1 获取该类的字节码文件对象
        Class<ReflectAnnotationTest> rac = ReflectAnnotationTest.class;
        //1.2 获取上面的注解对象,其实就是在内存中生成了一个该注解接口的子类实现对象
        AnnoReflect an = rac.getAnnotation(AnnoReflect.class);
        /*
        相当于
        public class AnnotationReflect implements AnnoReflect{
            public String className(){
                return "cn.other.annotation.AnnoTest1";
            }
            public String methodName(){
                return "play";
            }
        }
        */
        //2. 调用注解对象中定义的抽象方法,获取返回值
        String className = an.className();
        String methodName = an.methodName();
        }

在程序中使用注解:获取注解中定义的属性值

获取注解定义的位置的对象 (Class, Method, Field)
获取指定的注解:getAnnotation(Class)
调用注解中的抽象方法获取配置的属性值

网上经典教学案例

注解加反射监控检测一个类中的方法使用有异常,并进行统计

待测试的类
public class calculator {
 
    public void add(){
        System.out.println("1+0="+(1+0));
    }
 
    public void sub(){
        System.out.println("1-0="+(1-0));
    }
 
    public void mul(){
        System.out.println("1*0="+(1*0));
    }
 
    public void div(){
        System.out.println("1/0="+(1/0));
    }
    
    public void show(){
        System.out.println("今天天气真不错!");
    }
}

实现步骤

自定义一个注解

@Retention(RetentionPolicy.RUNTIME) //运行时
@Target(ElementType.METHOD) //加在方法前面
public @interface Check {
}

然后编写一个类专门用于检查(注意注释):

/** 简单的测试框架
 * 当主方法执行后,会自动自行检测所有方法(加了check注解的方法),判断方法是否有异常并记录
 */
public class TestCheck {
    public static void main(String[] args) throws IOException {
        //1. 创建计算机对象
        calculator c = new calculator();
        //2. 获取字节码文件对象
        Class cls = c.getClass();
        //3. 获取所有方法
        Method[] methods = cls.getMethods();
 
        int num = 0; //记录出现异常的次数
        BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));
 
        for(Method method:methods){
            //4. 判断方法上是否有Check注解
            if(method.isAnnotationPresent(Check.class)){
                //5. 有注解就执行,捕获异常
                try {
                    method.invoke(c);
                } catch (Exception e) {
                    e.printStackTrace();
                    //6.将异常记录在文件中
                    num++;
                    bw.write(method.getName()+"方法出异常了");
                    bw.newLine();
                    bw.write("异常的名称是:"+e.getCause().getClass().getSimpleName());
                    bw.newLine();
                    bw.write("异常原因:"+e.getCause().getMessage());
                    bw.newLine();
                    bw.write("=====================");
                    bw.newLine();
                }
            }
        }
        bw.write("本次测试一共出现"+num+"次异常");
        bw.flush();
        bw.close();
 
    }
 
}

在待测试的类中每个需要测试的方法前面都加上@Check

public class calculator {
    @Check
    public void add(){
        System.out.println("1+0="+(1+0));
    }
    @Check
    public void sub(){
        System.out.println("1-0="+(1-0));
    }
    @Check
    public void mul(){
        System.out.println("1*0="+(1*0));
    }
    @Check
    public void div(){
        System.out.println("1/0="+(1/0));
    }
 
    public void show(){
        System.out.println("希望没有bug");
    }
}

行TestCheck类中的主方法,就会自动检查所有注解@Check的方法是否异常

开发总结

大多数时候,我们会使用注解而不是自定义注解
注解给编译器和解析程序用(如TestCheck)
注解不是程序的一部分,可以理解为标签

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java自定义注解是一种元数据(metadata)的形式,它允许我们在代码中添加自定义的标记和信息。通过定义注解,我们可以为类、方法、字段等元素添加额外的信息,这些信息可以在编译时被读取,并用于生成代码、进行静态检查、运行时处理等。 自定义注解的定义使用`@interface`关键字,类似于定义一个接口或类。注解可以包含成员变量、方法、默认值等。成员变量可以是基本类型、字符串、枚举类型、注解类型或这些类型的数组。注解的方法可以没有参数或带有参数,可以有返回值或没有返回值。 以下是一个简单的示例,展示了如何定义一个自定义注解: ```java import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyAnnotation { String value() default ""; int number() default 0; } ``` 在上面的示例中,我们定义了一个名为`MyAnnotation`的自定义注解。它具有一个名为`value`的成员变量,默认值为空字符串,以及一个名为`number`的成员变量,默认值为0。注解使用了`@Retention`和`@Target`注解来指定注解的保留策略和作用目标。 使用自定义注解时,我们可以在需要标记的元素上使用注解,并为其成员变量赋值。例如: ```java public class MyClass { @MyAnnotation(value = "Hello", number = 42) public void myMethod() { // ... } } ``` 在上面的示例中,我们将自定义注解`MyAnnotation`应用到`myMethod`方法上,并为其成员变量`value`和`number`赋值。 在实际应用中,我们可以利用反射机制获取注解信息,并根据注解的信息执行相应的逻辑。自定义注解在框架和库的开发中经常被使用,例如Spring框架中的`@Autowired`和JUnit测试框架中的`@Test`等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值