注解也是jdk1.5的新特性
jdk内置注解
1、Java注解(Annotation):Override注解表示子类要重写(override)父类的对应方法。@Override
2、@Deprecated 表示方法是不建议被使用的
public class DeprecatedTest { @Deprecated public void doSomething() { System.out.println("do some thing"); } public static void main(String[] args) { DeprecatedTest test = new DeprecatedTest(); test.doSomething(); } }
3、@SuppressWarnings("unchecked") 注解表示抑制(压制)警告
4、Override、Deprecated注解都是Marker Annotation(标识性注解),注解名称本身即表示了要给工具程序的信息。
5、定义自己的注解:
public @interface AnnotationTest { } @AnnotationTest public class AnnotationUsage { @AnnotationTest public void method() { System.out.println("dadsa"); } public static void main(String[] args) { AnnotationUsage usage = new AnnotationUsage(); usage.method(); } }
定义注解使用@interface关键字,这里定义的相当于一个Marker Annotation
6、自定义注解带属性:
public @interface AnnotationTest { String value(); } @AnnotationTest(value="hello") public class AnnotationUsage { @AnnotationTest("world") public void method() { System.out.println("dadsa"); } public static void main(String[] args) { AnnotationUsage usage = new AnnotationUsage(); usage.method(); } }
自定义注解:当注解中的属性名为value时,在对其赋值时可以不指定属性的名字而直接写上属性值即可;除了value以外的其他都需要使用name=value这种复制形式,明确指定给谁赋值。例如AnnotationTest中定义的是String value1();则使用注解时必须这样:@AnnotationTest(value1="hello")
定义属性时设置默认值:String value1() fefault "hello";
当我们使用@interface关键字定义一个注解时,该注解隐含的继承了java.lang.annotation.Annotation接口,;如果我们定义了一个接口,并且让该接口继承自Annotation,那么我们所定义的接口依然还是接口而不是注解;Annotation本身是接口类型而不是注解。可以与Enum类比。
public @interface AnnotationTest { String value1() default "hello"; EnumTest value2(); } enum EnumTest { hello,world,welcome; } @AnnotationTest(value2=EnumTest.hello) public class AnnotationUsage { @AnnotationTest(value1="world",value2=EnumTest.world) public void method() { System.out.println("dadsa"); } public static void main(String[] args) { AnnotationUsage usage = new AnnotationUsage(); usage.method(); } }
7、告知编译器如何处理@Retention
java.lang.annotation.Retention型态可以在你定义Annotation型态时,指示编译程序该如何对待你的自定义的Annotation型态,预设上编译程序会将Annotation信息留在.class档案中,但不被虚拟机读取,而仅用于编译程序或工具程序运行时提供信息。在使用Retention型态时,需要提供java.lang.annotation.RetentionPolicy的枚举类型,三种值:CLASS,RUNTIME,SOURCE。
当为RUNTIME时,可以通过反射机制读取。SuppressWarnings注解是SOURCE的
RetentionPolicy为RUNTIME的时机,可以像是你使用Java设计一个程序代码分析工具,你必须让VM能读出Annotation信息,以便在分析程序时使用,搭配反射(Reflection)机制,就可以达到这个目的。
java.lang.reflect.AnnotatedElement接口,提供了一些方法,来对注解进行操作。
import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { String hello() default "shanghai"; String world(); } @MyAnnotation(hello="beijing",world = "tianjin") public class MyTest { @MyAnnotation(hello = "tianjin",world ="ddd") @Deprecated @SuppressWarnings("unchecked") public void output() { System.out.println("mytest"); } } import java.lang.annotation.Annotation; import java.lang.reflect.Method; public class MyReflection { public static void main(String[] args) throws Exception { MyTest myTest = new MyTest(); Class<MyTest> c = MyTest.class; Method method = c.getMethod("output",new Class[]{}); if(method.isAnnotationPresent(MyAnnotation.class)) { method.invoke(myTest,new Object[]{}); MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class); String hello = myAnnotation.hello(); String world = myAnnotation.world(); System.out.println(hello + "," + world); } Annotation[] annotations = method.getAnnotations(); for(Annotation annotation : annotations) { System.out.println(annotation.annotationType().getName()); } } }
8、限定annotation使用对象@Target
使用java.lang.annotation.Target可以定义其使用之时机(可以修饰哪些对象),在定义时要指定java.lang.annotation.ElementType的枚举值之一
ElementType的各个取值:TYPE:适用class,interface,enum;FIELD:适用field;METHOD:适用method;PARAMETER:适用method上的parameter;CONSTRUCTOR:适用constructor;LOCAL_VARIABLE:适用局部变量;ANNOTATION_TYPE:适用annotation类型;PAKAGE:适用package。
9、Documented注解:生成doc文档时注解出现
10、Inherited注解:注解是否会继承下来
11、注解在实际中的应用:JUnit单元测试(3.8版本,4.x版本):
对于3.8版本,继承TestCase,方法名以testXxx形式出现,反射得到所有方法,然后找到以test开头的方法,运行之。
对于4.x版本,使用注解加反射,JUnit4的执行的一般流程:
A)首先获得待测试类所对应的Class对象
B)然后通过该Class对象获得当前类中所有public方法所对应的Method数组。
C)遍历该Method数组,取得每一个Method对象
D)调用每个Method对象的isAnnotationPresent(Test.class)方法,判断该方法是否被Test注解所修饰。
E)如果该方法返回true,那么调用method.invoke()方法去执行该方法。,否则不执行。
单元测试不是为了证明你是对的,而是证明没有错误。Input is evil