java注解的使用

大家好,今天来写一篇有关java注解相关知识,以及对注解的一些简单运用,希望对你有所帮助。

首先来了解下注解的基本语法吧,java官方提供元注解四种:Target、Retention、Documented、Inherited,在声明注解时用于描述自身,其中Target和Retention基本都会用到。

@Target表示我们想要作用在什么地方

1.CONSTRUCTOR:构造器

2.FIELD:成员变量

3.LOCAL_VARIABLE:局部变量

4.METHOD:方法

5.PACKAGE:包

6.PARAMETER:方法参数

7.TYPE:类、接口(包括注解类型) 或enum声明

其中METHOD,FIELD,PARAMETER较常使用

@Retention 在哪一个级别可用

1.SOURCE:源文件中保留

2.CLASS:在class文件中保留

3.RUNTIME:运行时保留,配合反射较常使用

@Documented

可以生成注释文档

@Inherited

这个我也不太懂什么意思,没字面理解大概是可以被继承,较少使用。


再说下注解参数的可支持数据类型,即我们常用的 @xxx(此处的类型)

1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)

2.String类型

3.Class类型

4.enum类型

5.Annotation类型

6.以上所有类型的数组

如果只有一个参数的话命名最好是value(),后可跟一个默认值不加也可以,区别是没有默认值的话在使用的时候必须传入参数,而如果定义了默认值则可以不用传参。如:int value() default -1;

我们常见的应用方式如中@InjectView(参数),解释下这这句代码的意思,@InjectView代表注解类或者说注解对象吧,来看下怎么声明一个注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface InjectView {
    int value() default -1;
}
@Retention和@Target我们上面已经解释过了,这里的作用域是成员变量且在运行时保留,int value() default -1;代表声明一个int类型的参数,value为参数名,default -1表示一个默认值可以去掉,需要注意的是不使用默认值的话在应用时必须添加参数,而有默认值的话可不添加参数即使用@InjectView()亦可,多个参数按照同样的方式声明即可,参数若只有一个的话最好以value命名,有多个的话命名随意。我们也经常看到无参注解,这种类型为标记注解,如声明在某个方法上表示此处应做特殊处理。想要知道我们类中何处使用了注解就要通过反射了

下面准备了两个小例子实际运用,一个java、一个android,看了之后相信你们也会觉得很简单,代码中添加了注释,方便阅读。

java小例子

package annot;  
  
import java.lang.annotation.ElementType;  
import java.lang.annotation.Retention;  
import java.lang.annotation.RetentionPolicy;  
import java.lang.annotation.Target;  
  
/** 
 * Created by luojing on 2016/11/29. 
 */  
@Target(ElementType.METHOD)//声明使用在方法上  
@Retention(RetentionPolicy.RUNTIME)//运行时保留 
public @interface Annotation {  //声明注解
//可以定义默认值也可以不写,注意String不能用null做默认值。  
    String name() default "";  
      
    int age() default -1;  
}
package annot;
  
/** 
 * Created by luojing on 2016/11/29. 
 * 随便写的一个类用于测试
 */  
public class AnnotationTest {  
	//单个参数且命名为value时无需用=连接,直接填入值即可
    @Annotation(name = "luobo", age = 20)  
    private void get() {  
    }  
    //不写参数的使用默认值,没有默认值的话必须添加参数  
    @Annotation(name = "heihei")  
    public void post() {  
    }  
}

package annot;
  
import java.lang.reflect.Method;  
   
/** 
 * Created by luojing on 2016/11/29.
 * 调用测试 
 */  
public class AnotationDemo {  
  
  
    public static void main(String[] args) {  
        try {  
            //使用反射获取到class对象  
            Class<?> clazz = Class.forName("annot.AnnotationTest");  
            //获取类中声明的所有方法  
            Method[] declaredMethods = clazz.getDeclaredMethods();  
            if (declaredMethods.length >= 1) {  
                for (Method method : declaredMethods) {  
                    //method.getAnnotation(参数为定义的注解类的class对象)  
                    Annotation annotation = method.getAnnotation(Annotation.class);  
                    if (annotation != null) {  
                        //通过注解中的方法获取到值  
                        String name = annotation.name();  
                        int age = annotation.age();  
                        System.out.println("获取到的name是:" + name + "--age是:" + age);  
                    }  
  
  
                }  
            }  
  
  
        } catch (ClassNotFoundException e) {  
            e.printStackTrace();  
        }  
    }  
}

打印结果:

获取到的name是:luobo--age是:20

获取到的name是:heihei--age是:-1

----------------------------------------------------------------------------------------------------------------------

由于我是做android的,也会经常用到一些开源的注解框架,借此附上一个简单的Android注解demo,省略一大堆findViewById()。

当然优秀的第三方注解框架已经不是简单的通过反射设置了,如butterknife是在编译时解析,生成相关辅助java类,效率更高且不占用cpu。我这里只是简单运用下方便学习。

MainActivity 布局文件中声明一个TextView,一个ImageView,调用注解工具类解析,然后直接设置数据。

package example.luojing.annotationdemo.annot;  
  
  
import java.lang.annotation.ElementType;  
import java.lang.annotation.Retention;  
import java.lang.annotation.RetentionPolicy;  
import java.lang.annotation.Target;  
  
  
/** 
 * Created by luojing on 2016/11/30. 
 */  
@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.FIELD)  
public @interface InjectView {  
    int value() default -1;  
}

package example.luojing.annotationdemo.utils;  
  
import android.app.Activity;  
import android.view.View;  
  
import java.lang.reflect.Field;  
  
import example.luojing.annotationdemo.annot.InjectView;  
  
/** 
 * Created by luojing on 2016/11/30. 
 */  
public class InjectUtil {  
    public static void inject(Activity activity) {  
        //获取class对象  
        Class<? extends Activity> clazz = activity.getClass();  
        try {  
            // 通过反射获取类中的public成员变量,还有一个getDeclaredFields(),  
            // 区别是这个可以获取到所有访问权限符修饰的变量,  
            // 若要得到非public修饰的变量需调用setAccessible(true)进行暴力访问,  
            // Method、Annotation、Constructor中也是如此区分。  
            Field[] fields = clazz.getFields();  
            //遍历数组  
            for (Field field : fields) {  
                //判断该成员变量是否使用了注解,参数是我们自定义的注解类  
                if (field.isAnnotationPresent(InjectView.class)) {  
                    //获取到自定义注解对象  
                    InjectView annotation = field.getAnnotation(InjectView.class);  
                    //获取我们设置的值,如 @InjectView(R.id.xxx)  
                    //和上面一步可以简写成 field.getAnnotation(InjectView.class).value();  
                    int value = annotation.value();  
                    //...经常写的代码  
                    View view = activity.findViewById(value);  
                    //也可以通过反射获取  
                    //Method method = clazz.getMethod("findViewById", int.class);  
                    //View view = (View) method.invoke(activity,value);  
  
                    //通过反射给View赋值  
                    field.set(activity,view);  
                }  
            }  
        } catch (IllegalAccessException e) {  
            e.printStackTrace();  
        }  
    }  
}

package example.luojing.annotationdemo;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.TextView;

import example.luojing.annotationdemo.annot.InjectView;
import example.luojing.annotationdemo.utils.InjectUtil;

/**
 * Created by luojing on 2016/11/30.
 * 使用注解省略findViewById()
 */
public class MainActivity extends AppCompatActivity {
    @InjectView(R.id.tv_title)
    public TextView tvTitle;
    @InjectView(R.id.iv_content_pic)
    public ImageView ivContentPic;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        InjectUtil.inject(this);
        setData();
    }

    private void setData() {
        tvTitle.setText("文字设置成功");
        ivContentPic.setImageResource(R.drawable.beautiful_girl);
    }
}


以上大致如此,若有不对的地方请指正,希望对你有帮助。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值