关于注解你需要知道的

转载请标明出处:
http://blog.csdn.net/guangzq/article/details/74644624
本文出自祝起光的博客

什么是注解

注解是 Java 5 的一个新特性。注解是插入你代码中的一种注释或者说是一种元数据(meta data)。这些注解信息可以在编译期使用预编译工具进行处理(pre-compiler tools),也可以在运行期使用 Java 反射机制进行处理。这里存在着一个基本的规则:Annotation不能影响程序代码的执行,无论增加、删除 Annotation,代码都始终如一的执行。注解的行为就像

系统内置标准注解:

注解的语法比较简单,除了@符号的使用外,他基本与Java固有的语法一致,JavaSE中内置三个标准注解,定义在java.lang中:

  • @Override:用于修饰此方法覆盖了父类的方法;
  • @Deprecated:用于修饰已经过时的方法;
  • @SuppressWarnnings:用于通知java编译器禁止特定的编译警告。

元注解

元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解:

  • @Target,
  • @Retention,
  • @Documented,
  • @Inherited

下面一一说一下每个元注解的参数使用和作用

@Target

@Target注解的作用目标。说明了注解所修饰的对象范围,可以更加清晰注解所修饰的目标。

作用:描述注解的使用范围,即注解用在什么地方

ElementType取值作用目标
@Target(ElementType.ANNOTATION_TYPE)注解,就是用于描述注解本身
@Target(ElementType.CONSTRUCTOR)描述构造函数
@Target(ElementType.FIELD)字段(成员变量)、枚举的常量
@Target(ElementType.LOCAL_VARIABLE)局部变量
@Target(ElementType.METHOD)方法
@Target(ElementType.PACKAGE)
@Target(ElementType.PARAMETER)方法参数
@Target(ElementType.TYPE)类、接口(包括注解类型) 或enum声明

举例:

@Target(ElementType.METHOD)
public @interface MethodAnnotation {
    String value() default "";
}

@Target(ElementType.FIELD)
public @interface FieldAnnotation {
    String value() default "";
}

注解MethodAnnotation可以用来描述方法,FieldAnnotation可以用来描述字段、枚举的常量。

@Retention

@Retention定义了该注解的时间长短,即注解的生命周期。

作用:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)

ElementType取值作用目标
@Retention(RetentionPolicy.SOURCE)在源文件中有效(即源文件保留)
@Retention(RetentionPolicy.CLASS)在class文件中有效(即class保留)
@Retention(RetentionPolicy.RUNTIME)在运行时有效(即运行时保留)
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Person {
    public String name() default "fieldName";
    public String sex() default "fieldSex";
}

Person注解的的RetentionPolicy的属性值是RUTIME,这样注解处理器可以通过反射,获取到该注解的属性值,从而去做一些运行时的逻辑处理

@Documented

@Documented将此注解包含在Javadoc中。用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如Javadoc此类的工具文档化。Documented是一个标记注解,没有成员。

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Person {
    public String name() default "fieldName";
    public String sex() default "fieldSex";
}
@Inherited

允许子类继承父类中的注解。使用很少。

自定义注解

@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。

定义注解格式:

public @interface 注解名 {定义体}
 
举例:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RapperName {
    String value() default "";
}

注解参数的可支持数据类型:

  • 1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)
  • 2.String类型
  • 3.Class类型
  • 4.enum类型
  • 5.Annotation类型
  • 6.以上所有类型的数组

Annotation类型里面的参数该怎么设定:

  • 第一,只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型;   
  • 第二,参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();这里的参数成员就为String;  
  • 第三,如果只有一个参数成员,最好把参数名称设为”value”,后加小括号.

下面用一个自定义注解的例子来说明一下使用:

最近《中国有嘻哈》挺火,那我们就让rapper吴亦凡来dis一句 “你有freestyle吗?”

/**
 * Created by zhuqiguang on 17/7/6.
 * rapper名字
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RapperName {
    String value() default "";
}

是哪里的rapper呢?

/**
 * Created by zhuqiguang on 17/7/6.
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface RapperAdress {
    //住址枚举
    enum Adress{SICHUAN, BEIJING, SHANDONG}
    //住址属性
    Adress rapperAdress() default Adress.BEIJING;
}

rapper需要嘻哈装备

/**
 * Created by zhuqiguang on 17/7/6.
 */
public @interface RapperEquipment {
    //语言选项
    enum  Language{CHINESE, ENGLISH}
    //语言属性
    Language rapperLanguage() default Language.CHINESE;

    //说唱歌词
    String rapperLyrics() default "";
    //穿戴选项
    enum Clothing{GLASSES,  RING}
    Clothing rapperClothing() default Clothing.GLASSES;
}

组合成一个rapper

/**
 * Created by zhuqiguang on 17/7/6.
 */
public class Rapper {
    @RapperName("吴亦凡")
    private String rapperName;
    @RapperAdress(rapperAdress = RapperAdress.Adress.BEIJING)
    private String rapperAdress;
    @RapperEquipment(rapperLanguage = RapperEquipment.Language.CHINESE, rapperLyrics = "你有free style吗?", rapperClothing = RapperEquipment.Clothing.GLASSES)
    private String rapperEquipment;

    public String getRapperName() {
        return rapperName;
    }

    public void setRapperName(String rapperName) {
        this.rapperName = rapperName;
    }

    public String getRapperAdress() {
        return rapperAdress;
    }

    public void setRapperAdress(String rapperAdress) {
        this.rapperAdress = rapperAdress;
    }

    public String getRapperEquipment() {
        return rapperEquipment;
    }

    public void setRapperEquipment(String rapperEquipment) {
        this.rapperEquipment = rapperEquipment;
    }
}

利用反射来获取rapper字段

/**
 * Created by zhuqiguang on 17/7/6.
 */
public class RapperUtils {
    private static String Tag = "RapperUtils";

    public static void getRapperInfo (Class<?> clazz){
        String rapperName = "rapper名字: ";
        String rapperAdress = "rapper住址: ";
        String rapperEquipment = "rapper装备: ";
        Field[] declaredFields = clazz.getDeclaredFields();
        for(Field field: declaredFields) {
            if (field.isAnnotationPresent(RapperName.class)) {
                RapperName name = field.getAnnotation(RapperName.class);
                Log.d(Tag, rapperName + name.value());
            }else if (field.isAnnotationPresent(RapperAdress.class)) {
                RapperAdress adress = field.getAnnotation(RapperAdress.class);
                Log.d(Tag, rapperAdress + adress.rapperAdress().toString());
            }else if (field.isAnnotationPresent(RapperEquipment.class)) {
                RapperEquipment equipment = field.getAnnotation(RapperEquipment.class);
                String equ = "语言: " + equipment.rapperLanguage().toString() + " ,歌词: " + equipment.rapperLyrics() + " ,穿戴: " + equipment.rapperClothing().toString();
                Log.d(Tag, rapperEquipment + equ);
            }
        }
    }
}

main函数中调用

RapperUtils.getRapperInfo(Rapper.class);

输出结果:

rapper住址: BEIJING                                          
rapper装备: 语言: CHINESE ,歌词: 你有free style吗? ,穿戴: GLASSES     
rapper名字: 吴亦凡                                              

总结

注解在对于框架的构建以及简约代码有很大的作用,像Android中的通讯组件Router就是利用注解来设置通讯的路径,还有著名的Butternife,其原理是ButterKnifeProcessor在编译时会扫描你的Java代码中所有使用@BindView,@OnClick等注解,如果发现存在注解,那么通过一系列的解析工作,生成一个类似AnnotationActivity## ViewBinder(className##ViewBinder)的Java类,这个类实现了ViewBinder接口。这个生成类中实现了各注解对应的代码像@BindView最终会执行findViewById(),@OnClick最终会执行setOnClickListener()

本文demo中的源码地址:

参考

http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值