Annotation其實就是代碼里的特殊標記,可以在編譯,類加載,運行的時候被讀取,并執行相應的處理。在不改變原有邏輯的情況下,在源文件嵌入一些補充信息。一條重要原則:僅僅使用注解來標識程序元素,對程序不會造成任何影響,要讓注解起作用,必須為這些注解提供注解處理工具。
一、基本Annotation
- @Override 只能修飾方法,強制子類必須覆蓋父類的方法
- @Deprecated 表示某個程序元素(類、方法、接口等)已經過時,若其他程序使用該元素,將會給出警告
- @SuppressWarnings 被修飾的程序元素取消顯示指定的警告,會同時作用于該程序元素下的所有的子元素
二、自定義Annotation
1、定義Annotation
定義新的Annotation,使用@interface
關鍵字,與定義一個接口非常相似。所有的注解都繼承了Annotation接口。
public @interface Testable{
}
使用Annotation的語法,非常類似于public,final等修飾符(一般單獨放一行),通常用于修飾程序中的類 、接口、變量、方法等
public class MyClass {
@Testable
public void info() {
}
}
Annotation中還可以帶成員變量,用無參數的方法來聲明。方法名定義了成員變量的名字,返回值定義了成員變量的類型。語法與定義接口的語法非常相似。若沒有定義默認值,則必須賦值。
public @interface Testable {
String name();
int age() default 19;//已經設置默認值,使用時可以不賦值
}
//使用
public class MyClass {
@Testable(name="xiangyaohui")
public void info() {
}
}
標記Annotation:沒有成員變量,僅使用自身的存在與否,來為我們提供信息。
元數據Annotation:包含成員變量的Annotation,因為他們可以接受更多的元數據。
2、提取Annotation信息
AnnotatedElement接口中的三個方法
- <T extends Annotation> T getAnnotation(Class<T> aClass) //返回該類程序元素上,指定類型的注解,若該類型的注解不存在,返回null
- Annotation[] getAnnotations() //返回程序元素存在的所有注解
- boolean isAnnotationPresent(Class<? extends Annotation> aClass) //判定該程序元素上是否包含指定類型的注解
AnnotatedElement接口的實現類:
Class
Contrustor
Field
Method
Package
2.1、例子一
僅僅是一個標記Annotation,沒有成員變量
public @interface Testable {
}
public class MyClass {
@Testable
public void m1() {
}
public void m2() {
}
}
public class TestProcessor {
public static void process(String clazz) throws ClassNotFoundException {
for (Method m : Class.forName(clazz).getMethods()) {
//如果包含Testable標記注解
if (m.isAnnotationPresent(Testable.class)) {
try {
//調用m方法
m.invoke(null);
}catch (Exception e){
e.printStackTrace();
}
}
}
}
}
其實注解很簡單,就是為源碼添加一些特殊的標記,這些標記可以通過反射獲取,獲取到之后做出相應的處理。
2.2、例子二
public @interface ClickListenerFor {
//用于保存監聽器實現類
String listener();
}
public class ClickListenerProcessor {
public static void process(Object obj) {
try {
Class clazz = obj.getClass();
for (Field field : clazz.getFields()) {
field.setAccessible(true);
ClickListenerFor c = field.getAnnotation(ClickListenerFor.class);
if (c !=null){
//獲取元數據
Class listenerClazz = Class.forName(c.listener());
//
View.OnClickListener click = (View.OnClickListener) listenerClazz.newInstance();
//獲取field 實際對應的對象
Button button = (Button) field.get(obj);
//添加事件
button.setOnClickListener(click);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
public class MainActivity extends Activity {
@ClickListenerFor(listener = "OkClickListener")
private Button okButton;
@ClickListenerFor(listener = "CancelClickListener")
private Button cancelButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button1 = findViewById(R.id.button1);
Button button2 = findViewById(R.id.button2);
ClickListenerProcessor.process(this);
}
class OkClickListener implements View.OnClickListener {
@Override
public void onClick(View view) {
//點擊了確定按鈕
}
}
class CancelClickListener implements View.OnClickListener {
@Override
public void onClick(View view) {
//點擊了取消按鈕
}
}
}