Annotation其實(shí)就是代碼里的特殊標(biāo)記松捉,可以在編譯,類加載缘滥,運(yùn)行的時(shí)候被讀取轰胁,并執(zhí)行相應(yīng)的處理。在不改變?cè)羞壿嫷那闆r下朝扼,在源文件嵌入一些補(bǔ)充信息。一條重要原則:僅僅使用注解來標(biāo)識(shí)程序元素霎肯,對(duì)程序不會(huì)造成任何影響擎颖,要讓注解起作用榛斯,必須為這些注解提供注解處理工具。
一搂捧、基本Annotation
- @Override 只能修飾方法驮俗,強(qiáng)制子類必須覆蓋父類的方法
- @Deprecated 表示某個(gè)程序元素(類、方法允跑、接口等)已經(jīng)過時(shí)王凑,若其他程序使用該元素,將會(huì)給出警告
- @SuppressWarnings 被修飾的程序元素取消顯示指定的警告聋丝,會(huì)同時(shí)作用于該程序元素下的所有的子元素
二索烹、自定義Annotation
1、定義Annotation
定義新的Annotation弱睦,使用@interface
關(guān)鍵字百姓,與定義一個(gè)接口非常相似。所有的注解都繼承了Annotation接口况木。
public @interface Testable{
}
使用Annotation的語法垒拢,非常類似于public,final等修飾符(一般單獨(dú)放一行)火惊,通常用于修飾程序中的類 求类、接口、變量屹耐、方法等
public class MyClass {
@Testable
public void info() {
}
}
Annotation中還可以帶成員變量仑嗅,用無參數(shù)的方法來聲明。方法名定義了成員變量的名字张症,返回值定義了成員變量的類型仓技。語法與定義接口的語法非常相似。若沒有定義默認(rèn)值俗他,則必須賦值脖捻。
public @interface Testable {
String name();
int age() default 19;//已經(jīng)設(shè)置默認(rèn)值,使用時(shí)可以不賦值
}
//使用
public class MyClass {
@Testable(name="xiangyaohui")
public void info() {
}
}
標(biāo)記Annotation:沒有成員變量兆衅,僅使用自身的存在與否地沮,來為我們提供信息。
元數(shù)據(jù)Annotation:包含成員變量的Annotation羡亩,因?yàn)樗麄兛梢越邮芨嗟脑獢?shù)據(jù)摩疑。
2、提取Annotation信息
AnnotatedElement接口中的三個(gè)方法
- <T extends Annotation> T getAnnotation(Class<T> aClass) //返回該類程序元素上畏铆,指定類型的注解雷袋,若該類型的注解不存在,返回null
- Annotation[] getAnnotations() //返回程序元素存在的所有注解
- boolean isAnnotationPresent(Class<? extends Annotation> aClass) //判定該程序元素上是否包含指定類型的注解
AnnotatedElement接口的實(shí)現(xiàn)類:
Class
Contrustor
Field
Method
Package
2.1辞居、例子一
僅僅是一個(gè)標(biāo)記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標(biāo)記注解
if (m.isAnnotationPresent(Testable.class)) {
try {
//調(diào)用m方法
m.invoke(null);
}catch (Exception e){
e.printStackTrace();
}
}
}
}
}
其實(shí)注解很簡單蛋勺,就是為源碼添加一些特殊的標(biāo)記,這些標(biāo)記可以通過反射獲取鸠删,獲取到之后做出相應(yīng)的處理抱完。
2.2、例子二
public @interface ClickListenerFor {
//用于保存監(jiān)聽器實(shí)現(xiàn)類
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){
//獲取元數(shù)據(jù)
Class listenerClazz = Class.forName(c.listener());
//
View.OnClickListener click = (View.OnClickListener) listenerClazz.newInstance();
//獲取field 實(shí)際對(duì)應(yīng)的對(duì)象
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) {
//點(diǎn)擊了確定按鈕
}
}
class CancelClickListener implements View.OnClickListener {
@Override
public void onClick(View view) {
//點(diǎn)擊了取消按鈕
}
}
}