java注解初探

来源:互联网 发布:云计算的体系结构 编辑:程序博客网 时间:2024/06/11 05:33

ava注解在java5.0开始引入,是java中很重要的一部分。

元注解

  元注解是java注解中最基本的部分。它的作用是为其他注解进行注解,对其他注解起一个定义和说明的作用。元注解有4个:
* @Target
* @Retention
* @Documented
* @Inherited

1. @Target

  @Target用于描述对象的使用范围,或者说,被修饰的注解可以用在什么地方。
使用方法:

@Target(ElementType.FIELD)public @interface Column {}

其中ElementType分为7种:
1. CONSTRUCTOR 用于描述构造器的注解
2. FIELD 用于描述域的注解(描述类的成员变量)
3. LOCAL_VARIABLE 用于局部描述局部变量的注解
4. METHOD 用于描述方法的注解
5. TYPE用于描述类、接口(包括注解类型)、枚举的注解
6. PACKAGE用于描述包的注解
7. PARAMETER 用于描述参数的注解

2. @Retention

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

@Retention(RetentionPolicy.RUNTIME)public @interface Column {}

RetentionPolicy的类型有3种:
1. SOURCE:在源文件中有效(即源文件保留)
2. CLASS:在class文件中有效(即class保留)
3. RUNTIME:在运行时有效(即运行时保留)

  • SOURCE代表的是这个Annotation类型的信息只会保留在程序源码里,源码如果经过了编译之后,Annotation的数据就会消失,并不会保留在编译好的.class文件里面。

  • ClASS的意思是这个Annotation类型的信息保留在程序源码里,同时也会保留在编译好的.class文件里面,在执行的时候,并不会把这一些信息加载到虚拟机(JVM)中去.注意一下,当你没有设定一个Annotation类型的Retention值时,系统默认值是CLASS.

  • RUNTIME,表示在源码、编译好的.class文件中保留信息,在执行的时候会把这一些信息加载到JVM中去的.
      举一个例子,如@Override里面的Retention设为SOURCE,编译成功了就不要这一些检查的信息;相反,@Deprecated里面的Retention设为RUNTIME,表示除了在编译时会警告我们使用了哪个被Deprecated的方法,在执行的时候也可以查出该方法是否被Deprecated.

3. @Documented

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

@Documentedpublic @interface Column {}

4. @Inherited

  允许子类继承父类的注解。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。

@Inheritedpublic @interface Greeting {}

自定义注解

  我们使用@interface来自定义注解,在使用@interface自定义注解时,注解自动自动继承了java.lang.annotation.Annotation接口,此外不能再去继承任何接口或注解。
  @interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。

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

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

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

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

2. 利用反射解析注解并赋值

  1. 先自定义注解:
@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface Bind {    int value() default 0;}
  1. 自定义注解的使用主要还是在于解析的部分,因为需要用到反射机制,对反射不熟悉的话,很容易就卡在这边了。
public class Monker {    /**     * 传入activity作为参数     */    public static void inject(Activity activity) {        Class<?> cls = activity.getClass();        try {            //获取可访问的公共对象            Field[] fields = cls.getFields();            for (Field f : fields) {                //判断对象是否被Bind注解                if (f.isAnnotationPresent(Bind.class)) {                    //获取这个注解实例                    Bind n = f.getAnnotation(Bind.class);                    //获取注解的值                    int id = n.value();                    if (id > 0) {                        //如果注解不是默认值,那么赋值                        f.set(activity, activity.findViewById(id));                    }                }            }        } catch (IllegalAccessException e) {            e.printStackTrace();        }    }}

主要就是以上两部分,接下来看测试
xml部分:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout    xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/activity_main"    android:layout_width="match_parent"    android:layout_height="match_parent">    <TextView        android:id="@+id/tv"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="Hello World!"/></RelativeLayout>

MainActivity部分:

public class MainActivity extends AppCompatActivity {    @Bind(R.id.tv)    TextView name;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Monker.inject(this);        name.setText("注解");    }}

运行结果:

这里写图片描述

原创粉丝点击