1.Java注解是什么?
注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。(引用自百度百科)
2.注解有什么作用,为什么需要注解?
注解的作用大致分为三类:
a.编写文档:通过代码里标识的元数据生成文档。【生成doc文档】
b.代码分析:通过代码里标识的元数据对代码进行分析。【使用反射】
c.编译检查:通过代码里标识的元数据让编译器能够实现基本的编译检查【override】
心中有上面的两个概念后,就可以正式进入JAVA注解的学习了。
1.注解的分类
按运行机制来分,共有三种注解。
a.源码注解:只在源码中存在,编译成class文件就没有了
b.编译时注解:只在编译时起作用,注解在源码和class文件中都存在
c.运行时注解:在运行阶段还会起作用,甚至会影响运行逻辑的注解。
按注解来源来分,也有三种注解。
a.来自JDK的注解。
b.来自第三方的注解。
c.我们自己定义的注解。
2.Java中常见的注解
2.1JDK自带的注解
JDK自带的注解分为3个,@Override,@Deprecated,@Suppvisewarning.下面用程序说明这三个注解的用法.
2.1.1@Override
定义一个接口Parents.java
<span style="font-size:14px;">package com.example.zhujie;
public interface Parents {
public void age();
public void name();
}</span>
定义一个Son.java实现这个接口
<span style="font-size:14px;">package com.example.zhujie;
public class Son implements Parents{
@Override
public void age() {
// TODO Auto-generated method stub
}
@Override
public void name() {
// TODO Auto-generated method stub
}</span>
}
可以看到,编译器自动在age(),name()方法上添上了@Override,童鞋们可以想一下这个@Override有什么含义。。没错,这个的意思就是age(),name()方法已经在Parents接口中定义,你要实现这个接口,必须覆盖接口中的这些方法,它给编译器起一个提示的作用,告诉编译器这几个方法一定在你所实现的接口中存在。
2.1.2@Deprecated
Parents.java
Son.java
Parents.java中方法的上面有@Deprecated说明下面的这个方法已经过时,意思是这个方法在以后的版本中很可能被删除,最好别用,但其实它是个标注性注解,现在不影响程序,因为目前很有可能有的程序在用这个方法,但你用的时候它会给你警告,并在方法名上划一条线起标识作用。
2.1.3@Suppvisewarning
有矛就有盾,@Suppvisewarning就是来抑制编译器产生警告的。有三种使用@Suppvisewarning的格式.
@SuppressWarnings(“”)
@SuppressWarnings({})
@SuppressWarnings(value={})
示例:
· @SuppressWarnings("unchecked")
告诉编译器忽略 unchecked 警告信息,如使用List,ArrayList等未进行参数化产生的警告信息。
· @SuppressWarnings("serial")
如果编译器出现这样的警告信息:The serializable class WmailCalendar does notdeclare a static final serialVersionUID field of type long
使用这个注释将警告信息去掉。
· @SuppressWarnings("deprecation")
如果使用了使用@Deprecated注释的方法,编译器将出现警告信息。
使用这个注释将警告信息去掉。
· @SuppressWarnings("unchecked", "deprecation")
告诉编译器同时忽略unchecked和deprecation的警告信息。
· @SuppressWarnings(value={"unchecked", "deprecation"})
等同于@SuppressWarnings("unchecked", "deprecation")
2.2第三方的注解
由于作者的水平原因,并不了解关于第三方注解的一些知识,有兴趣的童鞋可以自己搜索查看。
3.自定义注解
3.1自定义注解的语法
//@interface是定义一个注解所必须的,既把class换成@interface就表示定义的是注解
public @interface De{
//声明成员的语法
String a();
String b();
//给成员赋初值的语法
int c() default 10;
}
注意,声明成员时,不能有参数,不能有异常,比如下面的语法就是错误的.
String a(int v) throws Exception;
3.2元注解的语法
@Target({ElementType.METHOD})
@Rentention(RententionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Fe{
String a();
String b();
}
注解Fe头上的四段代码就是元注解的基本语法,下来分别说明每段代码的作用
和它的参数的类型。
3.2.1@Target({XXX})
语法格式@Target({ElementType.XXX})
作用:用于描述注解的作用范围,既限定特定的注解用在特定的地方,凭借它的参数达到这一效果。
参数XXX包括以下几种情况:
a.CONSTRUCTOR用于构造函数
b.FIELD用于描述成员变量
c.LOCAL_VARIABLE用于描述局部变量
d.METHOD用于描述方法
e.PACKAGE用于描述包
f.PARAMETER用于描述参数
g.TYPE用于描述类,接口(包括注解类型),或enum声明
3.2.2@Retention
语法格式@Retention(RetentionPolicy.XXX)
作用:定义了该Annotation被保留的时间长短:某些Annotation仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。使用这个可以对 Annotation的“生命周期”限制。
参数XXX包括以下几种情况:
1.SOURCE:在源文件中有效,既在源文件中保留。
既在Class文件中保留。
既在运行时保留。
3.2.3@Inherited
语法格式:@Inherited
作用:@Inherited元注解是一个标记注解,如果使用了一个@Inherited修饰的注解用于一个class,则这个注解将被用于这个类的子类。
注意:@Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,方法并不从它所重载的方法继承annotation。
3.2.4@Documented
语法格式:@Documented
作用:@Documented是一个标注性注解,表示该注解可以被文档化。
3.3使用自定义注解
使用自定义注解的基本语法如下面的代码所示,包括了注解的定义和使用。
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Fe{
String a();
String b();
}
@Fe(a = "a",b = "b")
public void test(){
}
基本语法是@注解名(成员名=成员值,成员名=成员值,......)
3.4解析注解
基本概念:通过反射获取类,函数,或成员上的运行时注解信息,从而实现动态控制程序运行的逻辑。
首先定义一个注解,MyAnnotation.java
import java.lang.annotation.*;
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface MyAnnotation{
String value();
}
再定义一个使用注解的类,UseAnnotation.java
注意,当一个注解只有一个变量时,推荐变量名为value,使用注解时可以省略变量名和等号
<span style="font-size:18px;">@MyAnnotation("Class Annotation")
public class UseAnnotation {
@MyAnnotation("Method Annotation")
public void test(){
}
}</span>
然后开始解析注解,请各位小伙伴注意下面程序中的注释,此程序共说明了如何解析类上的和方法上的注解。
package com.example.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class ParseAnnotation {
public static void main(String[] args) throws Exception{
/**
* 解析类上的注解
*/
//第一步,使用类加载器加载你需要解析的类(那个类中包含你需要解析的注解)
Class c = Class.forName("com.example.annotation.UseAnnotation");
//第二步,判断类上是否有注解
boolean isExist1 = c.isAnnotationPresent(MyAnnotation.class);
if(isExist1){
//第三步,拿到注解的实例
MyAnnotation myAnnotation1 = (MyAnnotation) c.getAnnotation(MyAnnotation.class);
//第四步,输出值验证
System.out.println(myAnnotation1.value());
}
/**
* 第一种方法解析方法上的注解
*/
//第一步,首先获取所有方法
Method[] mes = c.getMethods();
for(Method mm : mes){
//第二步,找出那些有注解的方法
boolean isExist2 = mm.isAnnotationPresent(MyAnnotation.class);
if(isExist2){
MyAnnotation myAnnotation2 = mm.getAnnotation(MyAnnotation.class);
System.out.println(myAnnotation2.value());
}
}
/**
* 第二种方法解析方法上的注解
*/
for(Method mm : mes){
Annotation[] annotations = mm.getAnnotations();
for(Annotation a : annotations){
if(a instanceof MyAnnotation){
MyAnnotation myAnnotation3 = (MyAnnotation)a;
System.out.println(myAnnotation3.value());
}
}
}
}
}
后记:以上的内容就是一些比较基础的注解知识,看完这篇文章的小伙伴可以去看我的下一篇博客,实战注解,用一个实际的例子加深我们对注解的理解。