前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Java】注解

【Java】注解

作者头像
JuneBao
发布2022-10-26 14:43:05
8270
发布2022-10-26 14:43:05
举报
文章被收录于专栏:JuneBao

At the beginning, we are all children; in the end, we aspire to be angels.

Java注解

也叫元数据,用来给类,方法或属性添加一个“标记”

内置注解

代码语言:javascript
复制
// 标注该方法是重写父类的方法
@Override
代码语言:javascript
复制
// 标注过期弃用的方法,使用这种方法编译器会发出警告
@Deprecated
代码语言:javascript
复制
// 让编译器忽略有此标记的方法或类的警告
@SuppressWarnings("all")

自定义标注

注解定义

定义注解的格式:

代码语言:javascript
复制
public @interface 注解名 {
    // 注解属性
}

注解属性

也叫注解元素,类似于接口中方法的定义,只能包含一下类型,否则编译时就会报错

  1. 基本数据类型
  2. class
  3. String
  4. Annotation
  5. enum
  6. 以上数据类型的数组
代码语言:javascript
复制
package Note.annotation;

enum EnumDemo {
    MAX,
    MIN
}

public @interface AnnDemo {
    int age();
    String name();
    Check check();
    EnumDemo e();
    Class c();
    
    int [] ages();
    String [] names();
    EnumDemo [] ENUMS();
    Class [] classes();
    Check [] checks();
}
元素默认值

使用 default value设置默认值

代码语言:javascript
复制
public @interface AnnDemo {
    int age() default 18;
}

元注解

元注解是注解的注解,目的是方便注解的开发。

代码语言:javascript
复制
// 标注注解作用的位置
@Targer
代码语言:javascript
复制
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    ElementType[] value();
}
代码语言:javascript
复制
public enum ElementType {
    TYPE, // 作用于类,接口,Enum
    FIELD,  // 域声明
    METHOD,  // 作用于方法
    PARAMETER, // 参数声明
    CONSTRUCTOR, // 构造器声明
    LOCAL_VARIABLE,  // 作用于局部变量
    ANNOTATION_TYPE,
    PACKAGE,  // 作用于包
    TYPE_PARAMETER,
    TYPE_USE
}
代码语言:javascript
复制
//标注在什么级别保存该注解信息
@Retention
代码语言:javascript
复制
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}

public enum RetentionPolicy {
    SOURCE, // 源码级别,将被编译器丢弃
    CLASS,  // 注解在class文件中可用,但会被VM丢弃
    RUNTIME  // 在VM中也保留,因此可以使用反射读取注解信息,一般用这个
}
代码语言:javascript
复制
// 在DOC文档中保留注解
@Documented
代码语言:javascript
复制
// 子类继承父类注解
@Inherited

注解的本质

写一个简单的注解,javap反编译

代码语言:javascript
复制
package Note.annotation;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Check {
}
代码语言:javascript
复制
// 反编译的结果
Compiled from "Check.java"
public interface Note.annotation.Check extends java.lang.annotation.Annotation {
}

注解其实是一个继承自java.lang.annotation.Annotation的接口,

注解的使用

如果注解定义了元素,并且没给定默认值,需要在使用注解时给明确的值,格式为key = value

代码语言:javascript
复制
class Demo2 {

    @AnnDemo(name="liSi", check = @Check, e=EnumDemo.MAX, c=Demo.class, ages = {12, 13}, names = {"1", "2", })
    public void func(){
        System.out.println("hello world");
    }
}

如果只定义了一个元素,并且名字叫value,使用时可以不指定key

解析注解

步骤:

  1. 获取被注解装饰的类,方法,字段的class对象
  2. 调用class.getAnnotation(Class)方法获取注解对象
代码语言:javascript
复制
package Note.annotation;

@AnnDemo(name="liSi")
public class Demo2 {


    public static void main(String[] args) throws NoSuchMethodException {
        Class<Demo2> demo2Class = Demo2.class;
        AnnDemo annotation = demo2Class.getAnnotation(AnnDemo.class);
        String name = annotation.name();
        System.out.println(name);
    }
}

注解本事是一个接口,解析注解时,会在内存中生成一个实现了注解接口的子类对象,大致如:

代码语言:javascript
复制
public class xxx implements AnnDemo {
    public int age() {
        return 18;
    }
    
    public String name() {
        return "lisi"
    }
}

所以我们才能调用他的像name这样的方法。

简单的测试框架

代码语言:javascript
复制
package Note.annotation;

        import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Check {
}
代码语言:javascript
复制
package Note.annotation;

import 上课.interfacedemo.D;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MyCheck {

    public static void main(String[] args) throws IOException {
        Demo demo = new Demo();
        int errorNum = 0;
        Class<? extends Demo> aClass = demo.getClass();
        Method[] methods = aClass.getMethods();
        FileWriter fileWriter = new FileWriter("./src/Note/annotation/error.txt", true);
        fileWriter.write("\n" +aClass.getName() + "的测试结果 【" +
                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) +" 】 \n");
        fileWriter.write("======================================================================\n");
        for (Method m:methods
             ) {
            if(m.isAnnotationPresent(Check.class)) {
                try {
                    m.invoke(demo);
                } catch (Exception e) {
                    errorNum ++;
                    fileWriter.write(m.getName() + " 发生异常 " + "异常类型为:" + e.getCause().getClass().getSimpleName() + "\n");
                    fileWriter.write("异常原因为:" + e.getCause().getMessage() + "\n");
                    fileWriter.write("----------------------------------------------------------------------------------- \n");
                }
            }
        }
        fileWriter.write("======================================================================\n" +
                "测试结束,共发现" + errorNum + "个异常");
        fileWriter.close();
    }
}
代码语言:javascript
复制
package Note.annotation;

@SuppressWarnings("all")
public class Demo {
    @Check
    public void func1() {
        String s = null;
        s.toLowerCase();
    }

    @Check
    public void func2() {
        System.out.println("111");
    }

    @Check
    public void func3() {
        System.out.println(3/0);
    }

    @Check
    public void func4() {
        System.out.println(3 + "2");
    }
}
代码语言:javascript
复制
Note.annotation.Demo的测试结果 【2020-03-31 22:46:29 】 
======================================================================
func1 发生异常 异常类型为:NullPointerException
异常原因为:null
----------------------------------------------------------------------------------- 
func3 发生异常 异常类型为:ArithmeticException
异常原因为:/ by zero
----------------------------------------------------------------------------------- 
======================================================================
测试结束,共发现2个异常
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-3-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Java注解
    • 内置注解
      • 自定义标注
        • 注解定义
        • 注解属性
        • 元注解
        • 注解的本质
        • 注解的使用
        • 简单的测试框架
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档