注解也是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