一、什么是java注解
注解,顾名思义就是对某些事物进行标注说明,存放更多的信息。
在java层面,注解又叫java标注,java提供了一套机制,使得我们可以对方法、类、参数、包、域以及变量等添加标准(或附加信息,功能也算是信息的一部分),并且通过某些定义好的实际触发此段信息。
二、使用与自定义Java注解
1 为什么要自定义注解
Java从1.5版本以后默认内置三个标注:
@Override:只能用在方法之上的,用于覆盖父类方法(即重写父类方法,注意重载与重写的区别)。
@Deprecated:可用于方法、类、参数上、变量等之上(实际上是全部位置),用于标注为过期的方法、类、参数等,并在编译时提示告警信息。
@SuppressWarnings:可用于方法、类等之上(实际上是:TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE),用于忽略一些告警信息,例如忽略上述的@Deprecated过期提醒
但是,仅仅这三个标注是不能满足我们开发时一些需求的。所以java允许我们自定义注解来使用,了解spring boot等框架的同学会发现这些框架普遍且大量地自定义了许多注解并使用。
2 如何自定义注解
自定义步骤大致分为两步:
1.通过@interface关键字(注意,不是interface,是@interface)声明注解名称,并声明注解的成员属性(参数)。
2.使用java内置的四个元注解对这个自定义标注的范围、功能做出一定限制。
那么什么元注解呢?
3.什么是元注解
元注解,所谓元,即是原始的,基础的。元注解是构建注解的基础组成,元注解定义了衍生的注解,包括上述三个提到的注解,它们也是由元注解定义的。
元注解有哪些呢,全部的注解位于java.lang.annotation包下,主要有四个@Target,@Retention,@Documented,@Inherited
- @Target:表名注解用于什么地方,由枚举类ElemenetType指定,详细说明如下:ElemenetType.CONSTRUCTOR 构造器声明
ElemenetType.FIELD 域声明(包括 enum 实例)
ElemenetType.LOCAL_VARIABLE 局部变量声明
ElemenetType.METHOD 方法声明
ElemenetType.PACKAGE 包声明
ElemenetType.PARAMETER 参数声明
ElemenetType.TYPE 类,接口(包括注解类型)或enum声明 - @Retention:表示在什么级别保存该注解信息。可选的 RetentionPolicy 参数包括:
RetentionPolicy.SOURCE 注解将被编译器丢弃,即编译时忽略。
RetentionPolicy.CLASS 注解在class文件中可用,但会被VM丢弃 ,这是默认的级别。
RetentionPolicy.RUNTIME VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。 - @Documented:带有此元注解的注解,将会在javadoc或类似工具中生成对应文档记录。
- @Inherited:表示自动继承注解类型,这个元注释只会导致从超类继承注解; 已实现接口上的注解无效。
4 自定义及使用注解示例
自定义一个类级别的注解Description
import java.lang.annotation.*;
@Documented //将此注解包含在javadoc
@Target(ElementType.TYPE) //此注解作用于类
@Retention(RetentionPolicy.RUNTIME) //运行时生效
public @interface Description {
String value();
}
自定义一个字段、方法级别的注解
import java.lang.annotation.*;
@Documented //将此注解包含在javadoc
@Target({ElementType.METHOD, ElementType.FIELD}) //此注解作用于方法,字段
@Retention(RetentionPolicy.RUNTIME) //运行时生效
public @interface Name {
String name();
String description();
}
实现一个实体类,分别使用了类上的@Description、字段和方法上的@Name
@Description也可以写成@Description(“测试对应的注释”),因为注解定义的时候其字段为value。而value比较特殊,它在被指定参数的时候可以不用显示的写出来。
@Description(value = "测试对应的注释")
public class Person {
@Name(name = "临地-字段", description = "作用于字段")
private String name1;
public String getName1() throws NoSuchFieldException {
//获取字段name1上的Name注释的name值
return this.getClass().getDeclaredField("name1").getAnnotation(Name.class).name();
}
@Name(name = "临地-方法", description = "作用于方法")
public String getName2() throws NoSuchMethodException {
//获取getName2方法上的Name注释的name值
return this.getClass().getMethod("getName2").getAnnotation(Name.class).name();
}
}
main方法查看对应注解是否起效
public class RunMain {
public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException {
Person person = new Person();
Class personClass = person.getClass();
//输出类javadoc
if (personClass.isAnnotationPresent(Description.class)) {
Description dsc = (Description) personClass.getAnnotation(Description.class);
System.out.println("javadoc:" + dsc.value());
}
//获取对应的字段和方法注释,查看是否生效
System.out.println("字段注释:" + person.getName1());
System.out.println("方法注释:" + person.getName2());
}
}
注意事项:
所有的Annotation会自动继承java.lang.annotation这一个接口,所以不能再去继承别的类或是接口.
最重要的一点,Annotation类型里面的参数该怎么设定:
第一,只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型.
第二,参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();这里的参数成员就为String.
今天的文章Java中@ – 注解分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/26928.html