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

Java注解的用处和使用

作者头像
用户7886150
修改2021-04-08 11:04:38
8600
修改2021-04-08 11:04:38
举报
文章被收录于专栏:bit哲学院

参考链接: Java注解

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

Annotation 的作用 

Annotation 是一个辅助类,它在 Junit、Struts、Spring 等工具框架中被广泛使用。 

常见的作用有以下几种: 

生成文档。这是最常见的,也是java 最早提供的注解。常用的有@see @param @return 等;在编译时进行格式检查。如@Override放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出;跟踪代码依赖性,实现替代配置文件功能。比较常见的是spring 2.5 开始的基于注解配置。作用就是减少配置。现在的框架基本都使用了这种配置来减少配置文件的数量;在反射的 Class, Method, Field 等函数中,有许多于 Annotation 相关的接口。可以在反射中解析并使用 Annotation。 

内置的注解 

Java 定义了一套注解,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。 

作用在代码的注解是: 

@Override - 检查该方法是否是重载方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。@Deprecated - 标记过时方法。如果使用该方法,会报编译警告。@SuppressWarnings - 指示编译器去忽略注解中声明的警告。 

元注解是java API提供的,是用于修饰注解的注解,通常用在注解的定义上。四个元注解: 

@Target:注解的作用目标;@Retention:注解的生命周期;@Documented:将此注解包含在 javadoc 中 ,它代表着此注解会被javadoc工具提取成文档。在doc文档中的内容会因为此注解的信息内容不同而不同;@Inherited:是否允许子类继承该注解。 

@Target 用于指明被修饰的注解最终可以作用的目标是谁,也就是指明,你的注解到底是用来修饰方法的?修饰类的?还是用来修饰字段属性的。 可能的值在枚举类 ElemenetType 中,包括: 

ElementType.TYPE:允许被修饰的注解作用在类、接口和枚举上;ElementType.FIELD:允许作用在属性字段上;ElementType.METHOD:允许作用在方法上;ElementType.PARAMETER:允许作用在方法参数上;ElementType.CONSTRUCTOR:允许作用在构造器上;ElementType.LOCAL_VARIABLE:允许作用在本地局部变量上;ElementType.ANNOTATION_TYPE:允许作用在注解上;ElementType.PACKAGE:允许作用在包上。 

@Retention 表示在什么级别保存该注解信息。可选的参数值在枚举类型 RetentionPolicy 中,包括: 

RetentionPolicy.SOURCE:当前注解编译期可见,不会写入 class 文件RetentionPolicy.CLASS:类加载阶段丢弃,会写入 class 文件RetentionPolicy.RUNTIME:将在运行期也保留,可以反射获取。 

使用Annotation 

要获取类、方法和字段的注解信息,必须通过类的Class对象来获取 Annotation对象,除此之外没有别的获取注解对象的方法。 

获取Class对象有三种方式: 

通过类的静态成员表示。每个类都有一个隐含的静态成员class,如下: 

Class c1 = MyClass.class;

2.通过类对象的 getClass() 方法。由方法1不难理解,既然存在静态变量,那么通过对象的 getter 方法,就可以获取静态成员class: 

Class c2 = myClass1.getClass();

3.通过 Class 类的静态方法 forName() 方法获取 Class 的对象。区别于通过 new 创建对象(编译时静态加载),在开发时如果我们需要动态加载我们的功能模块,该方法可以帮助我们实现在程序运行时类的动态加载。 

try {

    //注意,forName()需要传入类的全路径

    //如果当前类与参数类在同一包下即可省略包名

    Class c3 = Class.forName("custom.MyClass");

} catch (ClassNotFoundException e) {

    e.printStackTrace();

}

得到类的Class对象后可以通过getAnnotation方法得到注解: 

 MyClassAnnotation myClassAnnotation = clazz.getAnnotation(MyClassAnnotation.class);

Spring动态加载类 

在Spring中可通过ApplicationContext容器来获取Bean。调用getBeansOfType方法可动态加载,获得指定类型的所有Bean对象。该方法返回一个Map类型的实例,Map中的key为Bean的名,key对应的内容为Bean的实例。 

Map beans = context.getBeansOfType(MyClass.class);

这种方式可通过公共接口实现动态代理。得到的Bean是代理对象,它和Bean里写的实现类没有关系, 只是把代理类接口中方法指向了实现类中的方法。这时如果通过代理对象的getClass()方法取Class对象将不会得到注解数据。 

解决方法是通过toString()方法获得实现类的类名,然后用Class.forName()得到实现类的Class对象。 

Class clazz = Class.forName(bean.toString().substring(0,bean.toString().indexOf("@")));

toString()方法是Object类里的一个实例方法,所有java类都是Object类的子类,因此所有java对象都具有toString方法。代理类继承了Proxy类,然后实现了Object里面的toString方法,所以输出的是实现类的类名。 

toString方法是一个”自我描述“方法,该方法默认返回该对象实现类的类名+@+hashCode值。可以通过字符串截取得到实现类的类名。

本文系转载,前往查看

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

本文系转载前往查看

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档