您的位置:首页 > 编程语言 > Java开发

java注解的使用

2016-11-30 11:53 225 查看
大家好,今天来写一篇有关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。我这里只是简单运用下方便学习。

MainActivi
4000
ty 布局文件中声明一个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);
}
}


以上大致如此,若有不对的地方请指正,希望对你有帮助。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java android annotation