Java基础复习——注解详细介绍
一.注解的概念
注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
对于注解的概念可简要概括为:
- JDK1.5之后的新特性
- 说明程序的
- 使用注解:@注解名称
关于注解的作用可以分为三类:
①编写文档:通过代码里标识的注解生成文档【生成doc文档】
②代码分析:通过代码里标识的注解对代码进行分析【使用反射】
③编译检查:通过代码里标识的注解让编译器能够实现基本的编译【Override】
下面我为大家演示一下生成doc文档:
首先新建下面文件:
/**
* @author jackTan
*/
public class JavaDocDemo {
/**
* @author jackTan
* @param a 参数1
* @param b 参数2
* @return 获得a与b的和
*/
public int getAdd(int a,int b){
return a+b;
}
}
来到该路径的命令行:
现在我们得到了doc文档。
二.JDK内置注解
- @Override :检测被该注解标注的方法是否是继承自父类(接口)的
- @Deprecated:该注解标注的内容,表示已过时
- @SuppressWarnings:压制警告, 一般传递参数all @SuppressWarnings(“all”)
演示:
未使用注解前,三条绿杠就是警告:
加入注解后警告消失:
当然把注解放在类前面那么所有的警告都消失.
三.自定义注解
1.注解的格式与本质
注解的格式是:
public @interface 注解名称{
属性列表;
}
还是JavaDemoDoc.java文件,内容如下:
下面我们来探寻他的本质。
public @interface JavaDocDemo {
}
从上图我们得到:
Compiled from “JavaDocDemo.java”
public interface JavaDocDemo extends java.lang.annotation.Annotation {
}
这说明注解的本质是一个继承了java.lang.annotation.Annotation的接口。
2.注解属性的定义
注解属性就是指注解的内容,这些内容其实就是抽象方法,只不过这些抽象方法的返回值只能是:
- 基本数据类型(byte,int,short,long,float,double,boolean,char)
- String
- 枚举
- 注解
- 以上类型的数组
还有一个要求就是在使用属性时要对属性赋值。(但是如果是有默认值可以不赋值。)
下面我们来对上面的内容做一个演示:
/**
* @author jackTan
*/
public @interface JavaDocDemo {
myAnno show1();
myAnno[] show1_();
String show2();
String[] show2_();
myEnum show3();
myEnum[] show3_();
int show4();
int[] show4_();
}
/**
* @author jackTan
*/
@interface myAnno{
}
enum myEnum{
}
下面我们只保留继续演示:
int show4();
由于没有默认值,我们要给show4赋值。
@JavaDocDemo(show4 = 1)
class TestAnno{
}
改为如下:
int show4() default 1;
这个时候有默认值,故而可以不赋值:
@JavaDocDemo()
class TestAnno{
}
然后我们再来演示一下数组赋值:
public @interface JavaDocDemo {
String[] show2_();
String[] show2();
}
//赋多个值要包上{},如果只有一个值可以省略{}
@JavaDocDemo(show2_ = {"a","b","c"},show2="a")
class TestAnno{
}
接下来要说一个特别的情况就是如果方法名叫做value并且只有他需要赋值,那么我们可以直接写值不写名。
把show方法改为:
int value();
那么这个时候:
@JavaDocDemo(1)
class TestAnno{
}
但是当不只有他一个要赋值呢?
public @interface JavaDocDemo {
int value();
myAnno show1();
}
这时必须写上value
@JavaDocDemo(value = 1,show1 = @myAnno)
class TestAnno{
}
3.元注解
元注解是用于描述注解的注解。
1.@Target:描述注解能够作用的位置
他的取值为枚举类型ElementType的成员。
//表示@JavaDocDemo只可以作用在类上
@Target(ElementType.TYPE)
public @interface JavaDocDemo {
String[] show2_();
String[] show2();
}
@JavaDocDemo(show2_ = {"a","b","c"},show2="a")
class TestAnno{
}
//表示@JavaDocDemo只可以作用在方法上
@Target(ElementType.METHOD)
public @interface JavaDocDemo {
String[] show2_();
String[] show2();
}
class TestAnno{
@JavaDocDemo(show2_ = {"a","b","c"},show2="a")
void get(){
}
}
//表示@JavaDocDemo只可以作用在成员变量上
@Target(ElementType.FIELD)
public @interface JavaDocDemo {
String[] show2_();
String[] show2();
}
class TestAnno{
@JavaDocDemo(show2_ = {"a","b","c"},show2="a")
int i;
}
还有些其他的读者自行尝试。
2.@Retention:描述注解被保留的阶段
@Retention(RetentionPolicy.RUNTIME):当前被描述的注解,会保留到class字节码文件中,并被JVM读取到
3.@Documented:描述注解是否被抽取到api文档中
被@Documented修饰的注解,在生成doc文档时会写出来,否则没有。
4.@Inherited:描述注解是否被子类继承
被@Inherited修饰的注解(假设我们叫A),如果@A修饰类,当该类作为父类被继承时,子类也被@A修饰。
四.解析注解
这一部分需要用到反射,这里举个案例就明白了。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author jackTan
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface JavaDocDemo {
String method();
String type();
}
/**
* @author jackTan
*/
@JavaDocDemo(method = "xxx" ,type = "int")
public class MainTest {
public static void main(String[] args) throws ClassNotFoundException {
Class<MainTest> testAnnoClass = MainTest.class;
JavaDocDemo annotation = testAnnoClass.getAnnotation(JavaDocDemo.class);
System.out.println(annotation);
System.out.println(annotation.method()+" "+annotation.type());
}
}
那么这里我要着重来强调一下就是一定要指明@Retention(RetentionPolicy.RUNTIME),否则使用getAnnotation()获取到的是null,同时注意包,千万别搞错了,因为在其他包下面也有同名的注解和类
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;