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提供的一种数据附加机制,这套机制可以实现对Filed
、Method
、Para
等存取额外的数据。
posted on 2021-12-28 00:06 shadow_fan 阅读(37) 评论(0) 编辑 收藏 举报