java注解初探

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是一个标记注解,没有成员。

@Documented
public @interface Column {
}

4. @Inherited

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

@Inherited
public @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)
@Documented
public @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("注解");
    }
}

运行结果:

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值