註解的使用和自定義註解
阿新 • • 發佈:2019-02-19
JDK中的三個基本註解
a、@Override:檢查子類確實是覆蓋了父類的方法。
b、@Deprecated:說明已經過時了。
c、@SuppressWarnings({ "unused", "deprecation" }):抑制程式中的警告。unused警告的型別。{}陣列。all抑制所有警告。
簡單使用:
public class Demo1 {
//@SuppressWarnings({ "deprecation", "unused" })
@SuppressWarnings("all")
public void fun()
{
int i = 5;
System.out.println("hello");
System.out.println(new Date().toLocaleString());
}
}
class Tests extends Demo1
{
@Override
public void fun()
{
super.fun();
}
@Deprecated
public void tt()
{
System.out.println(new Date().toLocaleString());
}
}
宣告一個註解 @interface 註解名{}
public @interface MyAnnotation{}
註解它的本質就是一個介面,這個介面需要繼承 Annotation介面。
public interface MyAnnotation extends java.lang.annotation.Annotation {
}
註解的屬性型別:
1.基本型別
2.String
3.列舉型別
4.註解型別
5.Class型別
6.以上型別的一維陣列型別
具體是怎樣定義的呢,我們看程式碼:
public @interface MyAnno1 {
//註解中定義的都是屬性
int age() default 20;
String[] name() default "hehe";
String value() default "haha";
Love love();
//MyAnno2 anno();
//public static final int num = 5;//可以
//public abstract void fun();//error
}
使用自定義註解:
public class Demo2 {
//@MyAnno1(age=25,name={"jack","lucy"},value="zhengzhi")
//@MyAnno1(value="zhengzhi")
@MyAnno1(value="zhengzhi",love=Love.eat)
public void tests()
{
}
}
如果在沒有預設值的情況下,使用自定義註解我們需要設定註解中屬性的值。
註解的反射:(靈魂)
模擬Junit的@Test
a、反射註解類
java.lang.reflect.AnnotatedElement:
<T extends Annotation> T getAnnotation(Class<T> annotationType):得到指定型別的註解引用。沒有返回null。
Annotation[] getAnnotations():得到所有的註解,包含從父類繼承下來的。
Annotation[] getDeclaredAnnotations():得到自己身上的註解。
boolean isAnnotationPresent(Class<? extends Annotation> annotationType):判斷指定的註解有沒有。
Class、Method、Field、Constructor等實現了AnnotatedElement介面.
如果:Class.isAnnotationPresent(MyTest.class):判斷類上面有沒有@MyTest註解;
Method.isAnnotationPresent(MyTest.class):判斷方法上面有沒有@MyTest註解。
下面通過程式碼實現一下。
我們模擬實現@Test註解的功能
首先這是我們的註解@MyTest
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
//元註解: 用來註解註解的
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {
long timeout() default Integer.MAX_VALUE;//設定超時時間的
}
這是我們使用註解的類:
public class DBCRUD {
@MyTest(timeout=1000000)
public void addTest()
{
System.out.println("addTest方法執行了");
}
@MyTest
public void updateTest()
{
System.out.println("updateTest方法執行了");
}
}
當我們使用了註解,我們就需要判該類是否使用了註解,我們通過反射來實現。
private static void method1() throws IllegalAccessException,
InvocationTargetException, InstantiationException {
Class claz = DBCRUD.class;//得到位元組碼檔案物件
//得到該類及父類中的所有方法
Method[] methods = claz.getMethods();
for(Method m:methods){
//判斷方法是否使用了@MyTest這個註解
// boolean boo = m.isAnnotationPresent(MyTest.class);
// System.out.println(m.getName()+"===="+boo);//都是false 預設註解存活到 CLASS,改變存活到RUNTIME
if(m.isAnnotationPresent(MyTest.class)){
m.invoke(claz.newInstance(), null);
}
}
}
**這裡我們需要注意的是,我們需要考慮到自定義註解的存活範圍。
預設的自定義註解只存活到編譯時期,class階段。
可以注意到,我們上面的自定義註解應用了@Retention註解,這個註解就是改變自定義註解的存活範圍。
這個註解也叫做元註解,只能用在註解上的註解叫做元註解。
**
上面的method方法沒有考慮到超時的問題,下面我們再完善一下。
//method1();
//反射解析註解的屬性
Class claz = DBCRUD.class;
Method[] methods = claz.getMethods();
for(Method m:methods){
//從該方法上獲取MyTest註解
MyTest mt = m.getAnnotation(MyTest.class);
if(mt!=null){
//得到註解中的屬性
long out = mt.timeout();
long start = System.nanoTime();
m.invoke(claz.newInstance(), null);
long end = System.nanoTime();
if((end-start)>out)
{
System.out.println("執行超時");
}
}
}