java 注解 属性 类型-凯发k8官方网
注解(annotation)相当于一种标记,在程序中加入注解就等于为程序打上某种标记以后,java编译器、开发工具或者其他的框架就可以通过反射来获取类以及类的成员上的注解,然后通过作相应的处理。
在方法上使用过的@override注解,编译器在编译时会检查方法是不是重写父类的方法。
在方法上使用的@deprecated注解表示方法已经过时,未来版本可能会删除
在变量、方法、类上使用的@suppresswarning(all) 忽略警告
在接口上定义的@functioninterface注解,编译器在编译时会检查该接口中是否只有一个抽象方法。
在方法上使用的@test注解,用于程序运行时检测是否符合testng单元测试方法规范。
后期再学习框架(mybatis,spring framework,springboot)时还会使用大量的注解配置来简化程序。
在开发框架时会使用到自定义注解,注解和类、接口、枚举(enum)是同级别关系。
自定义的注解格式如下
注解中可以包含0-n个属性,属性的定义个格式为:数据类型 属性名();,其中数据类型可以是如下几种
自定义注解@mytest,该注解没有属性
package net.ittimeline.java.core.jdk.feature.java5.annotation;/** * 自定义不含属性的注解 * * @author liuguanglei 18601767221@163.com * @version 2021/1/1 4:19 下午 * @since jdk11 */public @interface mytest { }注解定义完成之后就可以使用注解
/** * 在方法上使用没有属性的自定义注解@mytest */ @mytest public void testannotation() { }自定义包含多个属性的注解@table
package net.ittimeline.java.core.jdk.feature.java5.annotation;/** * 自定义带两个属性的注解 * * @author liuguanglei 18601767221@163.com * @version 2021/1/1 4:23 下午 * @since jdk11 */public @interface table { /** * 表名 * * @return */ string name() default " "; /** * 表名前缀 * * @return */ string prefix() default "tbl_";}然后可以在类上使用带属性的注解,给注解的属性赋值时,如果有多个属性,需要使用逗号分割。
/** * 在类上使用自定义注解@table * 多个属性赋值使用,分割 */@table(name = "tbl_user_info", prefix = "tbl_")class userinfo {}在使用注解时,有一些注意事项
- 如果注解有了属性,必须赋值,注解的属性可以有默认值,例如 string prefix() default "tbl_";表示prefix属性的默认值为tbl_,如果不想使用默认值,在使用注解时再给属性赋值。
- 如果属性的类型是一维数组,当数组的值只有一个的时候可以省略{}
- 如果注解中只有一个属性,并且属性名是value,那么给属性赋值时属性名value可以省略
jdk提供了@target、@retention两个元注解, 元注解表示定在注解上的注解。
- @target元注解用于限制注解作用在指定的位置上,默认注解可以在任意位置使用。
@target注解的value()属性取值类型是elementtype[]数组,常用的位置有elementtype.method 表示注解作用在方法上
elementtype.type 表示注解作用在类上
elementtype.field 表示注解作用在属性上
elementtype.constructor 表示注解作用在构造器上
package net.ittimeline.java.core.jdk.feature.java5.annotation;import java.lang.annotation.elementtype;import java.lang.annotation.target;/** * 自定义不含属性的注解 * * @author liuguanglei 18601767221@163.com * @version 2021/1/1 4:19 下午 * @since jdk11 */@target(elementtype.method) //自定义mytest注解只能作用在方法上public @interface mytest {}- @rentention :定义该注解保留在指定的阶段,取值为retentionpolicy类型,常用的取值有
retentionpolicy.source 注解保留在源码阶段
retentionpolicy.class 注解保留在编译阶段
retentionpolicy.runtime 注解保留在运行阶段
java程序的执行流程是从源码由javac编译生成字节码,然后由jvm解释运行,因此如果@retentinon注解的属性值是retentionpolicy.runtime ,意味着源码、编译和运行都会保留注解。
自定义注解@mytest,保留到运行阶段,只能作用在方法上
package net.ittimeline.java.core.jdk.feature.java5.annotation;import java.lang.annotation.elementtype;import java.lang.annotation.retention;import java.lang.annotation.retentionpolicy;import java.lang.annotation.target;/** * 自定义不含属性的注解 * * @author liuguanglei 18601767221@163.com * @version 2021/1/1 4:19 下午 * @since jdk11 */@target(elementtype.method) //自定义mytest注解只能作用在方法上@retention(retentionpolicy.runtime) //自定义mytest注解作用在运行阶段public @interface mytest {}自定义注解@table,只能作用在类上,保留到运行阶段
package net.ittimeline.java.core.jdk.feature.java5.annotation;import java.lang.annotation.elementtype;import java.lang.annotation.retention;import java.lang.annotation.retentionpolicy;import java.lang.annotation.target;/** * 自定义带两个属性的注解 * * @author liuguanglei 18601767221@163.com * @version 2021/1/1 4:23 下午 * @since jdk11 */@target(elementtype.type) //表示@table只能在类上使用@retention(retentionpolicy.runtime) // @table注解保存到运行阶段public @interface table { /** * 表名 * * @return */ string name() default " "; /** * 表名前缀 * * @return */ string prefix() default "tbl_";}系统自带的注解由系统解析,而自定义注解@table和@mytest默认只有标记,并没有其他的功能,如果想要注解提供额外的功能,就需要手动实现。
反射的api们class,field,constructor都实现了java.lang.reflect.annotatedelement接口
通过该接口提供的public a getannotation(class annotationclass)方法就可以获取指定的注解对象以及该对象的属性值
程序运行结果
不仅如此,我们还可以使用@mytest注解实现testng的@testng的功能
首先准备一个类,该类中包含了9个方法,其中有8个方法使用了@mytest注解,一个方法没有使用。
在testng框架中,要求可以执行的单元测试方法必须没参数,没返回值,访问权限必须是public,否则无法执行单元测试
然后编写一个处理该注解的handlemytestannotation方法,只需要传一个class对象即可。
/** * 处理@mytest注解,即会反射调用包含@mytest注解的方法 * * @param clazz * @param */ public void handlemytestannotation(class clazz) { //首先获取class对象的所有公共权限方法 method[] methods = clazz.getmethods(); try { // 然后创建class的对象 t type = clazz.newinstance(); //然后遍历每个方法 for (method method : methods) { //获取方法的名称 string methodname = method.getname(); //如果方法上使用了@mytest注解 if (method.isannotationpresent(mytest.class)) { //获取方法的返回值 class returntype = (class) method.getreturntype(); //方法的返回值必须是void if (returntype.getname().equals("void")) { //获取方法的参数 class>[] parametertypes = method.getparametertypes(); //方法必须无参数 if (parametertypes != null && parametertypes.length == 0) { //执行方法 method.invoke(type); } else { try { string message = "方法" methodname "方法必须没有参数"; throw new illegalargumentexception(message); } catch (illegalargumentexception ex) { ex.printstacktrace(); } } } else { try { string message = "方法" methodname "的返回值必须是void"; throw new illegalargumentexception(message); } catch (illegalargumentexception ex) { ex.printstacktrace(); } } } else { log.info("方法{}没有@mytest注解,不执行", methodname); } } } catch (invocationtargetexception | instantiationexception | illegalaccessexception e) { e.printstacktrace(); } }然后在测试方法中testhandlemytestannotation()中调用handlemytestannotation()方法传入orderhandler的class对象即可
/** * 测试解析@mytest注解 * * @see customannotationtest#handlemytestannotation(class) */ @test public void testhandlemytestannotation() { handlemytestannotation(orderhandler.class); }程序运行结果
总结
以上是凯发k8官方网为你收集整理的java 注解 属性 类型_跟光磊学java开发-java注解的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇:
- 下一篇: