java 注解 属性 类型_跟光磊学Java开发-Java注解
注解概述
注解(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元注解用于限制注解作用在指定的位置上,默認注解可以在任意位置使用。
@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 {}@Retention
- @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); }程序運行結果
程序運行結果
總結
以上是生活随笔為你收集整理的java 注解 属性 类型_跟光磊学Java开发-Java注解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: informix和mysql数据量_in
- 下一篇: active server pages