注解可以提供用来完整的描述程序所需的信息,而这些信息无法用java来表达的。所以,注解使我们能够以将由编译器来测试盒验证的格式。存储有个程序的额外信息。注解还可以用来生成描述符文件,甚至是新的类定义,并且有助于减轻编写样板代码的负担。使用注解还可以使代码更干净易读。
元数据是用来描述数据的数据,例如对于一副照片,照片本身是数据主体,但是像拍摄时间,照片大小都属于元数据范畴。注解就是java对元数据的支持。
java注解也就是Annotation,是java代码里的特殊标记。他为我们在代码中添加用java程序无法表达的额外信息提供了一种形式化的方法,使我们可以在未来的某一个时刻方便的使用这些被注解修饰的程序元素。程序元素包括类、方法、成员变量等。
注解,也就是java的元数据,是以标签的形式存在于java代码中的。注解的存在并不影响程序代码的编译和执行。它只是用来生成其他的文件,或使我们在运行时知道被运行代码的描述信息。
注解与注释:注解与普通的代码注释有一定的区别,也有一定的联系。注解和注释都属于对代码的描述;注释的作用只是简单的描述程序的信息,他不会被程序所读取;而注解则是java代码中的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相应的处理。
注解都是继承了java.lang.annotation.Annotation接口。注解的类型是一个接口。程序可以通过反射来获取指定程序元素的注解对象。
注解,提供了一条为程序元素关联任何元数据的途径。
使用注解的语法:使用注解时需要子啊其前面加一个“@”符号,同时将注解作为修饰符使用,用来修饰它所支持的程序元素。
注意:1、要将注解放在所有修饰符之前。2、通常将注解单独放置在一行。3、默认情况下,注解可用于修饰任何程序元素。4、一个程序元素不能被多个同一注解的实例同时修饰。
java中根据注解的使用方法和途径可以将注解分为三类:内建注解(也称为基本注解,定义于java.lang包下)、元注解(定义于java.lang.annotation包下)和自定义注解。
内建注解有三个分别是:1、限定重写父类方法@Override。2、标示已过时@Deprecated。3、抑制编译器警告:@SuppressWarnings。
四个元注解分别是:1、@Retention。2、@Target。3、@Documented。4、@Inherited。
自定义注解需要用到@interface关键字。
@Override是用来指定方法重写,他可以强制一个子类必须要重写父类的方法,@Override方法的使用:只要在要重写父类方法的子类方法前加上@Override即可。注意@Override只能用来修饰方法,而不能用来修饰其他的程序元素。
public class Fruit {
public void getObjectInfo(){
System.out.println("水果的getObjectInfo方法");
}
}
public class Apple extends Fruit {
@Override
public void getObjectInfo(){
System.out.println("水果的getObjectInfo方法");
}
}
@SuppressWarnings被用于有选择的关闭编译器对类、方法及成员变量等程序元素及其子元素的警告,该注解会一直作用于该程序元素的所有子元素。
@SuppressWarnings(value = name),当@SuppressWarnings后面的括号中的value值为如下参数时,编译器将取消其相应的警告:deprecation:使用了过时程序元素。unchecked:执行了未检查的转换。unused:有程序元素未被使用。
fallthrough:switch程序块直接通往下一种情况而没有break。path:在类路径、源文件路径等中有不存在的路径。serial:在可序列化的类上缺少serialVersionUID定义。finally:任何finally子句不能正常完成。all:所有情况。
@SuppressWarnings注解类型只定义了一个单一的成员变量,所以只需要一个name=value结构对为其赋值就可以了。如果成员变量值是一个数组,则要用大括号来声明数组值,如@SuppressWarnings(value={"unchecked","fallthrough"});
@SuppressWarnings(value={"unchecked","fallthrough"})
public class Apple extends Fruit{
public static void main(String args[]){
Apple a = new Apple();
@SuppressWarnings(value="unused")
List<Apple> list = new ArrayList();
list.add(a);
}
}
元注解:1、@Target用于指定被其修饰的注解能用于修饰那些程序元素。@Target注解类型有唯一的value作为成员变量,当value为如下值时则可指定被修饰的注解只能按如下声明进行标注。1、ANNOTATION_TYPE:注解声明。2、CONSTRUCTOR:构造方法声明。3、FIELD:成员变量声明。4、LOCAL_VARIABLE:局部变量声明。5、METHOD:方法声明。6、PACKAGE:包声明。7、PARAMETER:参数声明。8、TYPE:类、接口(包括注解类型)或枚举声明。
2、@Retention描述了被其修饰的注解是否被编译器丢弃或者保存在class文件中,如果保存在class文件中,是否在class文件被装载时被虚拟机所读取。默认情况下,注解被保存在class文件中,但在运行时并不能被反射访问。@Retention中唯一的value成员变量的取值,他只能有三个取值:1、RetentionPolicy.CLASS(默认值)表示编译器将把注解记录在class文件中,当运行java程序时,java虚拟机不再保留注解,从而无法通过反射对注解进行访问;RetentionPolicy.RUNTIME表示编译器将把注解记录在class文件中,当运行java程序时,java虚拟机也会保留注解,程序可以通过反射获取该注解、RetentionPolicy.SOURCE表示编译器将直接丢弃被修饰的注解。
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationTest{
//定义两个成员变量name和age
//用default关键字为两个成员变量赋初始值
String name() default "Jack";
int age() default 20;
}
3、@Documented注解,用于指定被其修饰的注解将被javadoc工具提取成文档,@Documented注解类型没有成员变量。
4、@Inherited注解:用于指定被其修饰的注解将具有继承性,如果某个类使用了定义时被@Inherited修饰的注解,则其子类会自动具有这个注解。
注意:被@Inherited注解修饰的注解是被标注过的类的子类所继承。类并不从它所实现的接口继承该类型的注解,方法也不能从它所重载的方法中继承这种注解。
自定义注解: 注解类型的关键字@interface而不是interface,@interface是继承java.lang.annotation.Annotation接口,而并非声明了一个新的interface接口。另外,注解类型的方法定义是独特的、受限制的,不同于普通接口中的方法定义。注解类型的方法必须声明为无参数、无异常抛出的。注解类型中的方法即为注解类型的成员变量。方法名就是成员变量名,方法返回值即为成员变量的类型。
注解的成员变量在注解类型的定义中以无参数方法的形式来声明,其方法名和返回值分别定义了该成员变量的名字和类型。
我们可以在定义注解类型的成员变量时为其指定初始值,指定成员变量初始值可以使用default关键字。
public @interface AnnotationTest{
//定义两个成员变量name和age
//用default关键字为两个成员变量赋初始值
String name() default "Jack";
int age() default 20;
}
根据注解类型是否包含成员变量,可以将注解分为两类“1、标记注解。没有定义成员变量的注解类型被称为标记。这种注解仅使用自身的存在与否,来为我们提供信息,2、元数据注解。包含成员变量的注解,因为他们可以接受更多的元数据,所以也被称为元数据注解。
获取注解信息:
public class MyAnnotation {
public static void main(String[] args) throws SecurityException, NoSuchMethodException, ClassNotFoundException {
MyAnnotation ma=new MyAnnotation();
ma.getObjectInfo();
}
@AnnotationTest
public void getObjectInfo() throws ClassNotFoundException, SecurityException, NoSuchMethodException{
@AnnotationTest
//获取MyAnnotation对象的getObjectInfo()方法所包含的所有注解
Annotation[] arr=Class.forName("com.pb.jadv.annotation.MyAnnotation").getMethod("getObjectInfo").getAnnotations();
//遍历每个注解对象
for(Annotation an:arr){
//如果an注解是AnnotationTest类型
if(an instanceof AnnotationTest){
System.out.println("an is "+an);
//将an强制类型转换成AnnotationTest
System.out.println("an.name(): "+((AnnotationTest)an).name());
System.out.println("an.age(): "+((AnnotationTest)an).age());
}
}
}
}