搞定神秘派之java注解

362 阅读3分钟

什么是注解

@Override重写 @Deprecated 已过期 这些都是我们常见的注解。

  • 从作用角度讲 注解是干嘛的呢?

注解是起到解释说明作用的。 比如@Override说明这个方法是重写的父类的方法,如果父类没有这个方法编辑器就会贴心的给你红线警告了

  • 本质上讲注解是什么呢

image
本质上讲注解是一个类一个接口。 这张图是在AndroidStudio 创建新Class是的面板从一个侧面作证这个观点,java类我们再熟悉不过了~

如何定义注解

源注解

定义一个注解就要先了解“元注解”,元注解就是修饰注解的注解主要是有以下四种

  • @Target,修饰注解的范围也就是说我们定义的这个注解可以用在什么地方

    • CONSTRUCTOR:用于描述构造器
    • FIELD:用于描述域
    • LOCAL_VARIABLE:用于描述局部变量
    • METHOD:用于描述方法
    • PACKAGE:用于描述包
    • PARAMETER:用于描述参数
    • TYPE:用于描述类、接口(包括注解类型) 或enum声明
  • @Retention,描述的是注解能修饰的生命周期,源码阶段,编译的class阶段和加载到JVM的RunTime阶段

  • @Documented, doc文档

  • @Inherited 用这个修饰的注解被用于类的时候 这个类的子类也被这个注解修饰

注解元素

注解元素就是注解主体里的一些抽象方法。抽象方法的特点是没有方法但是有返回值和方法名,而且注解里面的抽象方法没有方法参数。如下

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Student {
     int value();
     String name() default "";
}

特殊的当注解中只有一个方法并且方法名为value时可以不用写可以直接写value

如何使用

注解种的值可以使用反射获取到然后做相应的处理。

  • 创建注解
/**
 * Created by WESHAPE-DEV02 on 2017/12/21.
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface StudentDes {
    String name() default "";
    int ID() default -1;
}

特殊的当注解中只有一个抽象方法且方法名为value的时候z在使用注解添加属性值的时候可以不用标注使用(value = xxx)而是直接(XXX)

  • 使用注解
@StudentDes(ID = 1008,name = "Frank")
public class Student {
    String name ;
    int ID ;
    static void getStudent(Student student){
        Class<?extends Student> cls = student.getClass();
        StudentDes studentDes = (StudentDes) cls.getAnnotation(StudentDes.class);
        /**
         * 在注解中获取名字和学号
         */
        String name = studentDes.name();
        int ID = studentDes.ID();
        Field[] fields = cls.getFields();
        for(Field field:fields){
           if(field.getName().equals("name")) {
               try {
                   field.setAccessible(true);
                   field.set(student,name);//设置名字
               } catch (IllegalAccessException e) {
                   e.printStackTrace();
               }
           }else if (field.getName().equals("ID")){
               try {
                   field.setAccessible(true);
                   field.set(student,ID);//设置学号
               } catch (IllegalAccessException e) {
                   e.printStackTrace();
               }
           }
        }

    }
}

注解的运用

模拟一个butterknife的功能

  • 定义一个修饰Activity中View这种属性的注解如下:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BindView {
    int value();
     String getMyName() default "";
}
  • 写一个工具类
public class BindViewUtil {
    public static void binderView(Activity activity){
       Class<? extends Activity> mcls =  activity.getClass();
        Field[] fields = mcls.getFields();
        for(Field field:fields){
            BindView bindView = field.getAnnotation(BindView.class);
          if(bindView!=null)  {
              int viewID = bindView.value();
              bindView.getMyName();
              View view =  activity.findViewById(viewID);
              try {
                  field.setAccessible(true);
                  field.set(activity,view);
              } catch (IllegalAccessException e) {
                  e.printStackTrace();
              }
          }
        }
    }
}
  • 使用
public class MainActivity extends Activity {
    @BindView(R.id.view_a)
    TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        BindViewUtil.binderView(this);
    }

}

时间仓促,不免鄙陋,望诸君不吝指正。