frankfan的胡思乱想

学海无涯,回头是岸

Java注解

本章我们讨论的话题是【注解annotion

通俗理解,注解与注释没什么本质差别,都是【标注一段信息】然后【用来被解读】。

不同的是,注释是标注一段信息,然后供人(程序员)解读,起到说明某些代码的作用,这样的注释对代码或者 编译器没有约束或者额外的作用,全靠程序员的解读。

public class DemoClass{
    public void demofunc(){
        //不要轻易动下面的代码,有很多坑
        //the implementation...
    }
}
//这样的注释就是标注这个实现是有很多坑的,给程序员提供说明的信息,至于程序员最终决定是否改动这些代码,并没有实质的约束作用

而注解(annotion)也是提供一段信息,不过这段信息通过是需要【程序化】解读。当然,这段信息也可以不被解读(没有额外针对这段信息的解析代码),不过,不被解析的注解本身而言没有任何意义,因为,注解本身只提供一种标注,这个标注没有额外的功能。

public class MyActivity extends Activity{
   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
}
//@Override 就是注解,这个注解的目的并非给用户(程序员)提供注释,而是给编译器(IDE)提供额外信息,IDE会处理这个额外信息,结果就是既给用户标注了这是一个重写父类的函数,又给ide标注了这是个重写的函数,如果父类不存在这个函数,ide就会在编译期直接报错提醒用户。
//所以,对于注解而言,这个额外信息『想要』表达的信息是什么不是最重要,最重要的是怎么解析这个额外信息。那么,谁,怎么去解析这个额外信息呢?1、jdk库作者;2、框架作者;3、使用注解的那个类

自Java1.5后,Java便提供了一种「数据附加」的功能,用户(程序员)可以自由的 将一些数据附加到某个类、对象、参数、方法中,同时通过Java的反射功能,提供用户访问这些数据的权利,也就是说,用户可以对一个方法「set」数据,当然,你也可以「get」到这个数据。

//Node.java
class Node{
   @BindData(value = 11) //通过BindData这个注解我们给demofunc这个方法附加了一个数据11,BindData这个注解是我们自定义的。
    public void demofunc(){
			//implementation
    }
}
//BindData.java
//这指明了这个注解能用在什么地方,这里是只能用在方法上
@Target(ElementType.METHOD)
//这指明了这个注解信息能一直保留到「什么时候」,这里是一直到编译运行后,在虚拟机里运行时都依然保留注解的信息(通常也是自定义注解常用的,不然自定义注解也没啥意义了)
@Retention(RetentionPolicy.RUNTIME)
@interface BindData{
    int value() default 0;//格式写法;提供绑定一个int数据的能力
}

以上就是自定义注解的基本写法格式。

以上只是「定义」了一个注解,以及通过注解给方法「set」了一个值,那么怎么使用这个注解呢?

其实,具体的怎么使用取决于具体的业务逻辑,我们此处的所谓使用更多的是指「怎么获取」到set的这个值。答案是通过反射

//ParseAnnotion.java
class ParseAnnotion{
  public void parse(){
    Method demofunc_method = null;
        try {
            demofunc_method = MainActivity.class.getMethod("demofunc");//获取到MainActivity类中的demofunc方法
            BindData bindData =  (BindData) demofunc_method.getAnnotation(BindData.class);//获取到demofunc方法的注解信息
            Log.d("frankfandebugout",""+bindData.value());//直接拿到set的值
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
  }
}
//以上,是java通过反射API直接提供相关的获取注解信息,至于获取到value后,接下来的逻辑是什么,取决这个注解本身的功能设计了。

我们再详细讨论下@Target@Retention

//@Target有几种类型;
//类或接口:ElementType.TYPE
//字段:ElementType.FIELD
//方法:ElementType.METHOD
//构造方法:ElementType.CONSTRUCTOR
//方法参数:ElementType.PARAMETER

不同的@Target类型既意味着注解使用的场合的不同,同时也意味着能给什么绑定数据。

//BindPara.java
@Target({ElementType.PARAMETER,ElementType.METHOD,ElementType.FIELD})//这个注解可用在方法、方法参数以及实例变量上
@Retention(RetentionPolicy.RUNTIME)
@interface BindPara{
    int value() default 0;
}
//Node.java
class Node{
  @BindPara(value = 22)//给实例变量绑定22这个值
  private int num;
  
  //解析这个注解
  public void parseAnnotion(){
    try {
            Field num_field = Node.class.getDeclaredField("num");//针对性获取num这个变量,实际中通过是直接尝试获取这个类的所有Field
            if(num_field != null){
                BindPara bindPara = (BindPara)num_field.getAnnotation(BindPara.class);
                Log.d("frankfandebugout","num bind para = "+bindPara.value());
            }
        }catch (Exception e){}
  }
}

至此注解的自定义以及基本概念以及讨论完毕。

总结就是:注解是java提供的一种数据附加机制,这套机制可以实现对FiledMethodPara等存取额外的数据。

posted on 2021-12-28 00:06  shadow_fan  阅读(37)  评论(0编辑  收藏  举报

导航