Java-注解详解

一、Java注解

一)什么是注解

  • Annotation
  • 从JDK1.5开始引进,package java.lang.annotation中包含了所有定义自定义注解所需要的元注解与接口,所有的注解自动都实现了 java.lang.annotation.Annotation接口,类似于所有的类自动继承自Object类
  • 注解的作用:方便的在代码中添加信息,我们可以在以后的某个时间节点使用这些信息(通过反射解析注解)
  • 注解的常见作用
    • 生成文档,使用javadoc命令,常见的有注解有@see、@param、@return等
    • 跟踪代码的依赖性,实现替代配置文件的额功能,减少配置文件的数量
    • 在编译期进行格式检查,比如在重写父类方法时的@Override注解,用来检查方法是否为重写父类的。
  • 注解的定义格式
    • @interface 注解名{}
    • 可以作用在包、类、接口、注解、方法、成员变量等上面

二)内置注解

又称为基本注解,是Java官方提供的,直接使用就行了

  • @Override
    • 用来标记重写父类的方法
  • @Depercated
    • 过时的,标记过时的类、方法、成员变量
  • @SuppressWarning()
    • 用来阻止警告(黄线)
  • FunctionInterface
    • 标记指定的接口为函数式接口(可以使用lambda表达式)
    • 函数式接口:有且只有一个抽象方法

三)元注解

也是Java官方提供好的,作用是负责注解其他的注解,限定其他注解

  • @Target:标记注解的使用地方,可能的结果在枚举类ElementType中,包括如下:
参数作用范围
ElementType.TYPE类、接口、枚举、注解
ElementType.FIELD
ElementType.METHOD方法
ElementType.PARAMETER参数
ElementType.CONSTRUCTOR构造器
ElementType.LOCAL_VARIABLE局部变量
  • @Retention:描述注解的生命周期,表示在什么阶段保留该注解,可能结果在枚举类RetentionPolicy中。包括如下:
参数作用时间
RetentionPolicy.SOURCE编辑期
RetentionPolicyCLASS在Class文件中
RetentionPolicyRUNTIME在运行期,可以通过反射读取
  • @Documented:说明该注解被包含在javadoc中,可以被文档读取到
  • @Inherited:说明子类可以继承父类中的该注解

四)自定义注解及使用

  • 语法
    • @interface 注解名{}
  • 创建第一个注解
package edu.xiyou.annotations;

@MyAnnotation//在类上使用该注解
public class CreateAnnotation {
    
    @MyAnnotation//在成员变量上使用该注解
    public int i = 0;

    @MyAnnotation//在方法上使用该注解
    public static void main(String[] args) {
        System.out.println("第一个注解");
    }
}

@interface MyAnnotation {

}
  • 创建使用元注解修饰过的注解

上面我们创建了自己的注解,但是这个注解并没有携带什么信息,也没有起到什么作用,接下来我们使用元注解对自定义注解加以约束,四个元注解分别为@Target(作用地方)、@Retention(保存时间)、@Documented(生成文档)、@Inherited(注释能否被继承)

import java.lang.annotation.*;

public class ConstraintAnnotation {//使用元注解约束过的自定义注解练习

    //@MyAnnotation2 因为限定注释的作用范围在方法上,所以放在此处会报错
    private String str = null;

    @MyAnnotation2//可以放在此处
    public void Test() {
        System.out.println("测试方法");
    }
}

@Target(ElementType.METHOD)//限定该注解只能作用在方法上
@Retention(RetentionPolicy.SOURCE)//限定该注释只在编辑器有效,编译后就失效
@Documented//限定可以生成文档
@Inherited
//限定可以被子类继承注释
@interface MyAnnotation2 {

}
  • 创建带有属性的注解

上面我们虽然创建了自己的注解,也是用元注解约束了作用范围与失效时间等,但是依然没有一些参数进行描述,下来我们创建带有参数的注解。在注解中,每一个方法实际是声明了一个参数,方法名就是参数名,返回值类型就是参数的类型(返回值类型只能是基本数据类型、Class、String、枚举类型),可以使用default声明参数的默认值。

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

@MyAnnotation3(name = "ParamAnnotation", describe = "注解参数的测试类")//类上添加注解
public class ParamAnnotation {

    @MyAnnotation3(name = "zhangSan", type = "String", describe = "测试字段")//成员变量上添加注解
    private String str = "今天天气不错";

    @MyAnnotation3(name = "Test", describe = "我的测试方法")//方法上添加注解
    public void Test() {
        System.out.println("测试方法");
    }
}

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})//限定该注解能作用在成员变量、成员方法、类上
@Retention(RetentionPolicy.RUNTIME)//定义注解的生命期
@interface MyAnnotation3 {
    String name();//名字
    String type() default "";//类型
    String describe();//描述
}

/*
 当变量只有一个的时候,使用注解是可以不写变量名
 可以使用default关键字定义变量的默认值
*/
  • 使用反射注解的读取

我们创建注解就是为了在代码中添加描述信息,那添加了之后如何得到描述信息呢?这就要使用到反射了,使用反射读取注解的内容。

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

public class ReadAnnotations {//读取ParamAnnotation类中的注解

    public static void main(String[] args) throws ClassNotFoundException {
        getTypeAnnotations();//得到类注解信息
        getFieldAnnotations();//得到字段注解信息
        getMethodAnnotations();//得到方法注解信息
    }

    //得到类上的注解内容
    private static void getTypeAnnotations() throws ClassNotFoundException {
        Class pAClass = Class.forName("edu.xiyou.annotations.ParamAnnotation");//得到类的Class变量

        Annotation[] annotations = pAClass.getAnnotations();//得到类的所有注解
        for (Annotation annotation : annotations) {//遍历注解
            MyAnnotation3 myAnnotation3 = (MyAnnotation3) annotation;//强制转换成自定义注解类型

            //打印注解信息
            System.out.println("类注解\t名字:" + myAnnotation3.name() +
                    "\t类型:" + myAnnotation3.type() +
                    "\t描述:" + myAnnotation3.describe());
        }
    }

    //得到字段上的注解内容
    private static void getFieldAnnotations() {
        Field[] fields = ParamAnnotation.class.getFields();//得到类中的所有字段
        for (Field field : fields) {//遍历字段
            boolean b = field.isAnnotationPresent(MyAnnotation3.class);//判断字段是否含有注解

            if (b) {//如果有
                MyAnnotation3 annotation = field.getAnnotation(MyAnnotation3.class);//得到这个注解
                //打印注解的信息
                System.out.println("字段注解\t名字:" + annotation.name() +
                        "\t类型:" + annotation.type() +
                        "\t描述:" + annotation.describe());
            }
        }
    }

    //得到方法上的注解内容
    private static void getMethodAnnotations() {
        Method[] methods = ParamAnnotation.class.getMethods();//得到类中的所有方法
        for (Method method : methods) {//遍历方法
            boolean b = method.isAnnotationPresent(MyAnnotation3.class);//判断方法是否含有注解

            if (b) {//如果有
                MyAnnotation3 annotation = method.getAnnotation(MyAnnotation3.class);//拿到注解
                //打印注解信息
                System.out.println("方法注解\t名字:" + annotation.name() +
                        "\t类型:" + annotation.type() +
                        "\t描述:" + annotation.describe());
            }
        }
    }
}

/*运行结果
类注解	名字:ParamAnnotation	类型:	描述:注解参数的测试类
字段注解	名字:zhangSan	类型:String	描述:测试字段
方法注解	名字:Test	类型:	描述:我的测试方法*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值