30、注解(Annotation)

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

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值