注解详解
1、Annotation简介
简介
1、Annotation是java5开始引入的新特性,中文名称一般叫注解。它提供了一种安全的类似注释的机制,用来将任何的信息或元数据与程序元素(类、方法、成员变量、局部变量 ...)进行关联
2、更通俗的意思是为程序的元素(类、方法、成员变量)加上更直观更明了的说明,这些说明信息与程序的业务逻辑无关,并且提供指定的工具或框架使用的
3、Annotation像一种修饰符一样,应用于包、类、构造方法、方法、成员变量、参数及本地变量的声明语句中
原理
1、Annotation其实是一种接口。通过Java的反射机制相关的API来访问annotation信息。相关类(框架或工具中的类)根据这些信息来决定如何使用该程序元素或改变它们的行为。
2、annotation是不会影响程序代码的执行,无论annotation怎么变化,代码都始终如一地执行。
3、Java语言解释器在工作时会忽略这些annotation,因此在JVM 中这些annotation是“不起作用”的,只能通过配套的工具才能对这些annontaion类型的信息进行访问和处理。annotation的工具统称apt(Annotation processing tool)
2、常见的标准Annotation
@Override
@Override就是用来指定方法重写的,它可以强调一个子类必须要覆盖父类的方法
class Fruit{
public void info() { System.out.println("描述水果信息"); } }
class Apple extends Fruit{ @Override public void info() {
super.info(); System.out.println("我是苹果"); } }
public class Demo1 {
public static void main(String[] args) { Fruit fruit = new Apple(); fruit.info(); } }
@Deprecated
@Deprecated用于表示某个程序元素(类、方法等)已过时,当其它程序使已过时的类、方法时,编译器将会给出警告
class Person{ @Deprecated public void showInfo() { System.out.println("hello person"); } }
public class Demo2 { public static void main(String[] args) { Person person = new Person(); person.showInfo(); } }
@SuppressWarnings
@SuppressWarnings指示被Annotation标识的程序元素(以及在该程序元素中的所有子元素)取消显示指定的编译警告
class Container<T>{ private Object[] obj = null; public Container() { obj = new Object[10]; } @SuppressWarnings("unchecked") public T[] toArr() { return (T[])obj; } }
3、自定义Annotation
1、语法:
访问修饰符 @interface Annotation 名称{ 返回类型 method1() [default 默认值] }
2、特点:
1、Annotation类型使用关键字@interface而不是interface
2、Annotation类型方法必须声明为无参数、无异常抛出的。这些方法定义了annotation的成员:方法名成为了成员名,而方法返回值成为了成员的类型
3、方法返回值类型必须为基本类型、String类型、Class类型、枚举类型、annotation类型或者由前面类型之一作为元素的一维数组
4、方法的后面可以使用default和一个默认数值来声明成员的默认值,null不能作为成员默认值
5、在定义Annotation型态时,不能继承其它的Annotation型态或是接口
//标记注解 可以修饰类的任何成员 @interface MyAnnotation1{ }
public class MyAnnotation { @MyAnnotation1 public static void main(String[] args) { } }
@MyAnnotation1 public class MyAnnotation { public static void main(String[] args) { } }
public class MyAnnotation { @MyAnnotation1 private String name; public static void main(String[] args) { } }
@interface MyAnnotation2{
String name();
}
public class MyAnnotation { @MyAnnotation2(name="张三")//name必须写~如果是value就可以省略 public static void main(String[] args) { } }
@interface MyAnnotation3{
String value();
}
public class MyAnnotation { @MyAnnotation3("张三") public static void main(String[] args) { } }
@interface MyAnnotation4{
String value() default "张撒";
int age();
}
public class MyAnnotation { @MyAnnotation4(value="张三",age=12) public static void main(String[] args) { } }
@interface MyAnnotation5{
String[] value();
}
public class MyAnnotation { @MyAnnotation5({"张三","李四"}) public static void main(String[] args) { } }
enum Color{
Red,Blue
}
@interface MyAnnotation6{
Color value();
}
public class MyAnnotation { @MyAnnotation6(Color.Blue) public static void main(String[] args) { } }
4、Meta Annotation
1、概念:Meta Annotation也称为元Annotation,也是一种Annotation,可以对其它的Annotation进行注释
2、java5.0提供了一些标准的Meta Annotation
1、@Retention
@Retention(SOURCE/CLASS/RUNTIME) public/default @interface Annotation名称{...}
SOURCE:Annotation信息在编译阶段被丢弃,仅保留在java源文件中
CLASS(默认):Annotation信息在编译阶段被保留,保留到class文件当中,但是运行阶段不存在
RUNTIME:Annoation信息一直保留到运行阶段,直到退出虚拟机才被丢弃
以上三个值是java.lang.annotation.Retention这个类所提供的枚举值。作用:控制被Retention注释的Annotation信息保留时间长短
2、@Target
@Target({ElementType.METHOD,ElementType.TYPE}) public/default @interface Annotation名称{...}
@Target(ElementType.TYPE) //接口、类
@Target(ElementType.FIELD)//字段、枚举的常量
@Target(ElementType.METHOD)//方法
@Target(ElementType.PARAMETER)//参数
@Target(ElementType.CONSTRUCTOR)//构造函数
@Target(ElementType.LOCAL_VARIABLE)//局部变量
@Target(ElementType.ANNOTATION_TYPE)//注解
@Target(ElementType.PACKAGE) //包
3、@Documented
@Documented public/default @interface Annotation名称{...}
//生成java Doc 的时候会包含注解信息
4、@Inherited
@Inherited public/default @interface Annotation名称{...}
//标识性注解,容许子注解进行继承
5、反射与Annotation
一个Annotation真正起作用,必须结合反射机制,在java.lang.reflect反射包中提供AccessibleObject类来对Annotation进行操作,最常用的方法如下:
//判断是否使用指定的Anotation public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
//得到所有的Annotation public Annotation[] getAnnotations()
通过反射获取类注解信息
package com.note.reflection2; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Method; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented @interface Auther{ String name(); String group(); } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @interface Description{ String value(); } @Description("这是一个用来测试的类") class AnnotationTest { @Auther(name="张三",group="com.im") public void test() { System.out.println("test -----------------"); } } public class Demo2 { /*** * 通过反射获取类注解信息 * @param args * @throws Exception */ public static void main(String[] args) throws Exception { Class<?> cc = Class.forName("com.note.reflection2.AnnotationTest"); if(cc.isAnnotationPresent(Description.class)) { Description description = cc.getAnnotation(Description.class); System.out.println("Description's Description->" + description.value()); Method[] methods = cc.getMethods(); for(Method method : methods) { if(method.isAnnotationPresent(Auther.class)) { Auther auther = method.getAnnotation(Auther.class); System.out.println("Auther-->" + auther.name() + " " + auther.group()); } } } } }
运行结果:
Description's Description->这是一个用来测试的类 Auther-->张三 com.im