java用 @interface Annotation{ } 定義一個註解 @Annotation,一個註解是一個類。java
@Override,@Deprecated,@SuppressWarnings爲常見的3個註解。數組
在Servlet3.0就是使用了註解,在Spring中用的更多框架
註解至關於一種標記,在程序中加上了註解就等於爲程序加上了某種標記,之後,ide
JAVAC編譯器,開發工具和其餘程序能夠用反射來了解你的類以及各類元素上有無任何標記,看你有什麼標記,就去幹相應的事。工具
註解@Override用在方法上,當咱們想重寫一個方法時,在方法上加@Override,當咱們方法學習
的名字出錯時,編譯器就會報錯開發工具
註解@Deprecated,用來表示某個類的屬性或方法已通過時,不想別人再用時,在屬性和方法spa
上用@Deprecated修飾,就是在一個方法上畫一條橫線,在IDE中能夠明顯看到,表明過期.net
註解@SuppressWarnings用來壓制程序中出來的警告,好比在沒有用泛型或是方法已通過時的時候,開發
註解@Retention能夠用來修飾註解,是註解的註解,稱爲元註解。
Retention註解有一個屬性value,是RetentionPolicy類型的,Enum RetentionPolicy是一個枚舉類型,
這個枚舉決定了Retention註解應該如何去保持,也可理解爲Rentention 搭配 RententionPolicy使用。RetentionPolicy有3個值:CLASS RUNTIME SOURCE
用@Retention(RetentionPolicy.CLASS)修飾的註解,表示註解的信息被保留在class文件(字節碼文件)中當程序編譯時,但不會被虛擬機讀取在運行的時候;
用@Retention(RetentionPolicy.SOURCE )修飾的註解,表示註解的信息會被編譯器拋棄,不會留在class文件中,註解的信息只會留在源文件中;
用@Retention(RetentionPolicy.RUNTIME )修飾的註解,表示註解的信息被保留在class文件(字節碼文件)中當程序編譯時,會被虛擬機保留在運行時,
因此他們能夠用反射的方式讀取。RetentionPolicy.RUNTIME 可讓你從JVM中讀取Annotation註解的信息,以便在分析程序的時候使用.
[java] view plaincopy
package com.self;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTarget
{ }
定義個一註解@MyTarget,用RetentionPolicy.RUNTIME修飾;
package com.self;
import java.lang.reflect.Method;
public class MyTargetTest
{
@MyTarget
public void doSomething()
{
System.out.println("hello world");
}
public static void main(String[] args) throws Exception
{
Method method = MyTargetTest.class.getMethod("doSomething",null);
if(method.isAnnotationPresent(MyTarget.class))//若是doSomething方法上存在註解@MyTarget,則爲true
{
System.out.println(method.getAnnotation(MyTarget.class));
}
}
}
上面程序打印:@com.self.MyTarget(),若是RetentionPolicy值不爲RUNTIME,則不打印。 覺得沒有被放進class文件中
@Retention(RetentionPolicy.SOURCE )
public @interface Override
@Retention(RetentionPolicy.SOURCE )
public @interface SuppressWarnings
@Retention(RetentionPolicy.RUNTIME )
public @interface Deprecated
由上能夠看出,只有註解@Deprecated在運行時能夠被JVM讀取到
註解中能夠定義屬性,看例子:
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation
{
String hello() default "gege";
String world();
int[] array() default { 2, 4, 5, 6 };
EnumTest.TrafficLamp lamp() ;
TestAnnotation lannotation() default @TestAnnotation(value = "ddd");
Class style() default String.class;
}
上面程序中,定義一個註解@MyAnnotation,定義了6個屬性,他們的名字爲:
hello,world,array,lamp,lannotation,style.
屬性hello類型爲String,默認值爲gege
屬性world類型爲String,沒有默認值
屬性array類型爲數組,默認值爲2,4,5,6
屬性lamp類型爲一個枚舉,沒有默認值
屬性lannotation類型爲註解,默認值爲@TestAnnotation,註解裏的屬性是註解
屬性style類型爲Class,默認值爲String類型的Class類型
看下面例子:定義了一個MyTest類,用註解@MyAnnotation修飾,註解@MyAnnotation定義的屬性都賦了值
@MyAnnotation(hello = "beijing", world="shanghai",array={},lamp=TrafficLamp.RED,style=int.class)
public class MyTest
{
@MyAnnotation(lannotation=@TestAnnotation(value="baby"), world = "shanghai",array={1,2,3},lamp=TrafficLamp.YELLOW)
@Deprecated
@SuppressWarnings("")
public void output()
{
System.out.println("output something!");
}
}
接着經過反射讀取註解的信息:
public class MyReflection
{
public static void main(String[] args) throws Exception
{
MyTest myTest = new MyTest();
Class<MyTest> c = MyTest.class;
Method method = c.getMethod("output", new Class[] {});
//若是MyTest類名上有註解@MyAnnotation修飾,則爲true
if(MyTest.class.isAnnotationPresent(MyAnnotation.class))
{
System.out.println("have annotation");
}
if (method.isAnnotationPresent(MyAnnotation.class))
{
method.invoke(myTest, null); //調用output方法
//獲取方法上註解@MyAnnotation的信息
MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
String hello = myAnnotation.hello();
String world = myAnnotation.world();
System.out.println(hello + ", " + world);//打印屬性hello和world的值
System.out.println(myAnnotation.array().length);//打印屬性array數組的長度
System.out.println(myAnnotation.lannotation().value()); //打印屬性lannotation的值
System.out.println(myAnnotation.style());
}
//獲得output方法上的全部註解,固然是被RetentionPolicy.RUNTIME修飾的
Annotation[] annotations = method.getAnnotations();
for (Annotation annotation : annotations)
{
System.out.println(annotation.annotationType().getName());
}
}
}
上面程序打印:
have annotation
output something!
gege, shanghai
3
baby
class java.lang.String
com.heima.annotation.MyAnnotation
java.lang.Deprecated
若是註解中有一個屬性名字叫value,則在應用時能夠省略屬性名字不寫。
可見,@Retention(RetentionPolicy.RUNTIME )註解中,RetentionPolicy.RUNTIME是註解屬性值,屬性名字是value,
屬性的返回類型是RetentionPolicy,以下:
public @interface MyTarget
{
String value();
}
能夠這樣用:
@MyTarget("aaa")
public void doSomething()
{
System.out.println("hello world");
}
註解@Target 也是用來修飾註解的元註解,它有一個屬性ElementType也是枚舉類型,
值爲:ANNOTATION_TYPE CONSTRUCTOR FIELD LOCAL_VARIABLE METHOD PACKAGE PARAMETER TYPE
如@Target(ElementType.METHOD) 修飾的註解表示該註解只能用來修飾在方法上。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTarget
{
String value() default "hahaha";
}
如把@MyTarget修飾在類上,則程序報錯,如:
@MyTarget
public class MyTargetTest
註解大都用在開發框架中(Spring,Servlet3.0...),好了有關注解就學習那麼多了,謝謝。