Java注解

元数据

元数据是指用来描述数据的数据(“data about data”),简单的说,就是描述代码间关系,代码本身,资源数据等的数据。一般是结构化数据(如存储在数据库里的数据,规定了字段的长度、类型等)。元数据是指从信息资源中抽取出来的用于说明其特征、内容的结构化的数据。
比如,关于一本书(信息资源),我们在图书馆系统中检索可以得到题名,版本、出版数据、相关说明,包括检索点等,这些就是元数据,用于描述资源的。

Java注解

JDK5.0引入了Annotation的概念来描述元数据,在java中,元数据是以标签的形式存在,元数据并不会影响程序代码的编译和执行。JDK5.0出来后,java语言中有四种类型,class(类)、enum(枚举)、interface(接口)和@interface(注解),他们在java中处于同一级别。元数据在java中,既是由注解来表示的。注解可以在编译、类加载和运行时被读取。
Java的注解本质上是一个接口,继承了接口Annotation的接口,这里的继承用的是extends。

注解既然和接口类似,就会包含成员:

  • final静态属性,必须初始化
  • 公共抽象方法,可设置默认值

@interface隐含继承Annotation,但是自定义注解不能直接继承Annotation。直接继承的是接口,非注解。

注解的作用

  1. 编写文档(通过代码里面标识的元数据编写,例如@param,@return)
  2. 代码分析(可以替代配置文件)
  3. 编译检查(通常配合lint使用,如@override 放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出。)

Java中自带的注解

(基本)

  1. @Override(限定重写父类的方法)
  2. @SuppressWarning(用于抑制编译器产生警告信息)
  3. @Deprecated(表示"已过时/不建议使用/在后期的API中可能被删除")
  4. @SafeVarargs(java7新增,和堆污染有关,具体不是很了解)
    (用于标识注解的注解)
  5. @Retention(决定注解存活和读取时间,它包含一个RetationPolicy的value成员变量,用于指定它所修饰的注解的读取和存活时间)
    一般的值有:
    • Retationpolicy.CLASS:在类加载的时候解读,执行的时候,jvm就会抛弃掉。
    • Retationpolicy.ROURCE:存在于源码中,在编译的时候解读,之后就抛弃,不进入类加载和运行环节。
    • Retationnpolicy.RUNTIME:运行时解读,可以在运行时通过反射获取注解,执行操作。
  6. @Target (指定修饰的元素,包含一个value值)
    value可选:
    • ElementType.ANNOTATION_TYPE: 指定该Annotation只能修饰Annotation。
    • ElementType.CONSTRUCTOR: 指定只能修饰构造器。
    • ElementType.FIELD: 指定只能成员变量。
    • ElementType.LOCAL_VARIABLE: 指定只能修饰局部变量。
    • ElementType.METHOD: 指定只能修饰方法。
    • ElementType.PACKAGE: 指定只能修饰包定义。
    • ElementType.PARAMETER: 指定只能修饰参数。
    • ElementType.TYPE: 指定可以修饰类,接口,枚举定义。
  7. @Document(可被javadoc提取成文档)
  8. @Inherited 被他修饰的Annotation具有继承性

自定义注解

最简单的例子,Android中代替findviewById()对组件进行初始化。只需要在成员变量组件前加上注解就行,能有效的减少代码量,可读性更强。

首先定义注解,运行时读取,作用于成员变量
写法和接口雷同
用法是@FindView(R.id.XXX)这里传入的Id就是这个value的返回值,可以在获取到这个注解实例后调用这个value() 方法获取值
可以不止一个方法,多一个方法,就可以多传一个参数,如果有默认值,也可以不传

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FindView{
    /**
     * id 注解,这里没有默认值,不过可以自由添加,
     * 例如:public String tableName() default "className";
     * @return
     */
    int value();
}

从上面注解的定义来,类似于接口,所以注解本身不具备解析和其他操作的功能,这里我们想要的是利用这个注解携带的value,初始化这个注解所表示的成员变量,所以我们需要自己写一个工具类,通过传入的activity获取注解,并利用反射初始化成员变量。以下是详细代码:

public class ViewUtil {
    public static void viewInject(Activity activity){
        viewInjects(activity);
    }

    private static void viewInjects(Activity activity){
        Class<? extends Activity> clazz = activity.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for(Field field:fields){
            FindView viewFind = field.getAnnotation(FindView.class);
            if(viewFind!=null){
                int viewId = viewFind.value();
                View view = activity.findViewById(viewId);
                try {
                    field.setAccessible(true);
                    field.set(activity, view);

                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

最后是具体的使用方法

public class MainActivity extends AppCompatActivity {
       @FindView(R.id.btn)
    Button btn;
    @FindView(R.id.btn1)
    Button btn1;
    @FindView(R.id.btn2)
    Button btn2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ViewUtil.viewInject(this);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                btn.setText("Test2");
            }
        });
    }
}

以上是@Retention(RetentionPolicy.RUNTIME)运行时解读的具体写法。
优点是可读性强,写起来简单。
缺点便是常驻内存,并利用反射进行初始化,耗费内存

如何解决这个问题呢?其实我们可以利用apt,使用编译时解读或者类加载时解读,后面的文章我会重点讲到,这里就不多啰嗦了。

So easy!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,264评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,549评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,389评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,616评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,461评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,351评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,776评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,414评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,722评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,760评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,537评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,381评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,787评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,030评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,304评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,734评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,943评论 2 336

推荐阅读更多精彩内容

  • 本文章涉及代码已放到github上annotation-study 1.Annotation为何而来 What:A...
    zlcook阅读 29,090评论 15 116
  • 内容概要 Annotation的概念 Annotation的作用 Annotation的分类 系统内置注解 元注解...
    DevinZhang阅读 4,138评论 0 28
  • 一、什么是注解? 注解对于开发人员来讲既熟悉又陌生,熟悉是因为只要你是做开发,都会用到注解(常见的@Overrid...
    _Justin阅读 1,337评论 0 10
  • 一辆Morgan +4停在了Brook Street 69号门口,一位身着皮革驾车装的绅士从车中走出,快步进入了S...
    时尚先生Esquire阅读 454评论 0 0
  • 事与愿违之同工同酬法 同工同酬法不管它的用意多么善良,但在实际效果上,它剥脱了那些竞争力比较弱的人跟竞争力强的人展...
    蒙山布衣阅读 154评论 0 0