`
whp0731
  • 浏览: 170355 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java5.0新特性总结--Annotation系统学习整理笔记

    博客分类:
  • J2SE
阅读更多

Java Annotation特性与使用方式
一、为什么使用Annotation
在JAVA应用中,我们常遇到一些需要使用模版代码的情况。例如,为了编写一个 web service,我们必须提供一对接口和实现作为模版代码。如果使用annotation对远

程访问的方法代码进行修饰的话,这个模版就能够使用工具自动生成。
另外,一些API需要使用与程序代码同时维护的附属文件。例如EJB需要一个部署描述符。此时在程序中使用annotation来维护这些附属文件的信息将十分便利而且减少

了错误。

二、Annotation工作方式(应知道如何定义,如何使用)
从Java5.0版发布以来,5.0平台提供了一个正式的annotation功能:允许开发者定义、使用自己的annotation类型。此功能由一个定义annotation类型的语法和一个描

述annotation声明的语法,读取annotation的API,一个使用annotation修饰的class文件,一个annotation处理工具(apt)组成。
annotation并不直接影响代码语义,但是它能够工作的方式被看作类似程序的工具或者类库,它会反过来对正在运行的程序语义有所影响。annotation可以从源文件、

class文件或者以在运行时反射的多种方式被读取。
当然annotation在某种程度上使javadoc tag更加完整。一般情况下,如果这个标记对java文档产生影响或者用于生成java文档的话,它应该作为一个javadoc tag;否

则将作为一个annotation。

三、使用JDK5内建Annotation
参见程序实例
Override
Deprecated
SuppressWarnings

 

 1、Override重写(子类、父类间关系)而overload(重载,方法间)

Override强制的保障已经覆盖了父类的方法, 如此处toString()大写成ToString(),它就会提示你出错了。

public class OverrideTest
{
	@Override
	public String toString()
	{
		return "This is override";
	}

	public static void main(String[] args)
	{
		OverrideTest test = new OverrideTest();

		System.out.println(test.toString());
	}
}

 2、Deprecated
被@Deprecated标示的方法是一个不建议被使用的方法

DeprecatedTest.java,申明作者以前定义的方法doSomething可能会有问题,不介意使用了!

当你再去使用或者再从该类去继承都会出现警告信息!

public class DeprecatedTest
{
	@Deprecated
	public void doSomething()
	{
		System.out.println("do something");
	}
	
	public static void main(String[] args)
	{
		DeprecatedTest test = new DeprecatedTest();
		test.doSomething();
	}
}

 3、SuppressWarnings

import java.util.Date;
import java.util.Map;
import java.util.TreeMap;

public class SuppressWarningsTest
{//仅去掉集合的警告如下:@SuppressWarnings("unchecked")
	//以下表示压制住两个类型的警告
	@SuppressWarnings({"unchecked","deprecation"})
	public static void main(String[] args)
	{//没有用泛型,在jdk1.5,会出现警告!
		Map map = new TreeMap();	
		map.put("hello",new Date());
		
		System.out.println(map.get("hello"));
		
		DeprecatedTest test = new DeprecatedTest();
		test.doSomething();
		
	}
}

 


四、自定义Annotation类型

使用@interface自行定义Annotation型态时,实际上是自动继承了java.lang.annotation.Annotation接口;;如果我们手工地显示地区定义一个接口public interface test

extents Annotation,这个test接口不是Annotation。
它要隐式地为你实现,由编译程序自动为您完成其它产生的细节
在定义Annotation型态时,不能继承其它的Annotation型态或是接口

 

public @interface AnnotationTest//这个后面不能显示地再去继承别的接口
{
 //在Annotation类中定义属性方法,需要多一个小括号
 //例如:String value();
 //然后在使用的地方需要对这个value赋值,如在别的 类中需要@AnnotationTest(value="hello world")
 //value是默认表述,可以省略@AnnotationTest("hello world"),但如果改成value1必须显示申明
 String value();
}

 

 

 

 

 

 

@AnnotationTest("hello world")
public class AnnotationUsage
{
	public void method()
	{
		System.out.println("usage of annotation");
	}

	public static void main(String[] args)
	{
		AnnotationUsage usage = new AnnotationUsage();
		usage.method();
	}
}

 

扩展以上两个例子

package com.test;
public @interface AnnotationTest
{
	//在Annotation类中定义属性方法,需要多一个小括号
	//例如:String value();
	//然后在使用的地方需要对这个value赋值,如在别的 类中需要@AnnotationTest(value="hello world")
	//value是默认表述,可以省略@AnnotationTest("hello world"),但如果改成value1必须显示申明
	String value() default "ok";//用defaulf关键字可以定义默认值
	
	//枚举类型的value1,默认值是hello
	//EnumTest value1() default EnumTest.Hello;
	
	//String[] value2();
}

enum EnumTest
{
	Hello, World, Welcome;
}

 

package com.langsin.test;
@com.test.AnnotationTest(value="hello world")//或者可以导入包import com.test然后写成AnnotationTest(value="hello world")//@AnnotationTest(value1="EnumTest.World")
//@AnnotationTest(value2={"hello","world"})

public class AnnotationUsage
{
	public void method()
	{
		System.out.println("usage of annotation");
	}

	public static void main(String[] args)
	{
		AnnotationUsage usage = new AnnotationUsage();
		usage.method();
	}
}

 


五、告知编译程序如何处理@Retention 

 

 java.lang.annotation.Retention型态可以在您定义Annotation型态时,指示编译程序该如何对待您的自定义的Annotation型态
预设上编译程序会将Annotation信息留在.class档案中,但不被虚拟机读取,而仅用于编译程序或工具程序运行时提供信息

在使用Retention型态时,需要提供java.lang.annotation.RetentionPolicy的枚举型态{}中为它的三个级别!
package java.lang.annotation;
public enum RetentionPolicy
 {
  SOURCE, //编译程序处理完Annotation信息后就完成任务(被编译程序废弃)
  CLASS,  //编译程序将Annotation储存于class档中,缺省
  RUNTIME //编译程序将Annotation储存于class檔中,可由jVM读入(可以通过反射方式读取注解相关信息)
}

 

 

RetentionPolicy为SOURCE的例子是@SuppressWarnings
仅在编译时期告知编译程序来抑制警告,所以不必将这个信息储存于.class档案
RetentionPolicy为RUNTIME的时机,可以像是您使用Java设计一个程序代码分析工具,您必须让VM能读出Annotation信息,以便在分析程序时使用
搭配反射(Reflection)机制,就可以达到这个目的

 

 如何使用?以下程序为演示程序
演示程序

1、Annotation类的定义中不能定义日期类变量、也不能定义二维数组。

2、AnnotatedElement接口介绍
<T extends Annotation> T         getAnnotation(Class<T> annotationType)
                                 Returns this element's annotation for the specified type if such an annotation is present, else null.
                               
Annotation[] getAnnotations()    Returns all annotations present on this element.


Annotation[] getDeclaredAnnotations()
                                 Returns all annotations that are directly present on this element.(即不包括父类)

 

boolean isAnnotationPresent(Class<? extends Annotation> annotationType)
                                 Returns true if an annotation for the specified type is present on this element, else false.
3、程序介绍

 

package com.langsin.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation
{
 String hello() default "langsin";
 String world();
}



package com.langsin.annotation;

@MyAnnotation(hello = "beijing", world = "shanghai")
public class MyTest
{
 @MyAnnotation(hello = "beijing", world = "shanghai")
 @Deprecated
 @SuppressWarnings("unchecked")
 public void output()
 {
  System.out.println("output something");
 }
}




package com.langsin.annotation;

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[]{});
   //以下方法的具体含义可以参见AnnotatedElement接口介绍的具体介绍!
   MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
   //myAnnotation.hello();这句话的意思是此时的MyAnnotation的属性需要按按类似方法的式样进行调用。
   String hello = myAnnotation.hello();
   String world = myAnnotation.world();
   
   System.out.println(hello);
   System.out.println(world);
   
  }
  
  Annotation[] annotations = method.getAnnotations();
  
  for(Annotation annotation : annotations)
  {
   System.out.println(annotation.annotationType().getName());
  }
  
 }
} 

/*
 * 运行结果
output something
beijing
shanghai
com.langsin.annotation.MyAnnotation
java.lang.Deprecated
说明:为什么运行结果中没有java.lang.SuppressWarnings。因为在jdk文档中我们可以发现SuppressWarnings的定义中为@Retention(value=SOURCE)
而 SOURCE, //编译程序处理完Annotation信息后就完成任务(被编译程序废弃)
   CLASS,  //编译程序将Annotation储存于class档中,缺省
   RUNTIME //编译程序将Annotation储存于class檔中,可由jVM读入(可以通过反射方式读取注解相关信息)
   也就是说只有当@Retention的value值为RUNTIME时才会被虚拟机运行时加载!

*/

 

六、限定annotation使用对象@Target
1、使用java.lang.annotation.Target可以定义其使用之时机
在定义时要指定java.lang.annotation.ElementType的枚举值之一
package java.lang.annotation;
public enum ElementType
{
     TYPE, //适用class, interface, enum
     FIELD, //适用field
     METHOD, //适用method
     PARAMETER, //适用method上之parameter
     CONSTRUCTOR, //适用constructor
     LOCAL_VARIABLE, //适用局部变量
     ANNOTATION_TYPE, //适用annotation型态
     PACKAGE //适用package

}


2、程序举例
package com.langsin.annotation;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
//定义完以上@Target(ElementType.METHOD),以后MyTarget这个Annotation只能用在方法上了!
public @interface MyTarget
{
 String value();
}


package com.langsin.annotation;
public class MyTargetTest
{
 @MyTarget("xyz")
 public void doSomething()
 {
  System.out.println("hello world");
 }
}


七、要求为API文件@Documented
1、想要在使用者制作JavaDoc文件的同时,也一并将Annotation的讯息加入至API文件中
使用java.lang.annotation.Documented

2、程序举例

package com.langsin.annotation;

import java.lang.annotation.Documented;

@Documented//这句话的意思是生成doc文档时,包括annotation的信息。
public @interface DocumentedAnnotation
{
 String hello();
}


package com.langsin.annotation;

public class DocumentedTest
{
 /**
  * This is the comments that I have added
  */
 @DocumentedAnnotation(hello = "welcome")
 public void method()
 {
  System.out.println("hello world");
 }
}

 

八、子类是否继承父类@Inherited
1、预设上父类别中的Annotation并不会被继承至子类别中
可以在定义Annotation型态时加上java.lang.annotation.Inherited型态的Annotation

2、程序举例

package com.langsin.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
@Inherited//这个注解决定了使用这个Annotation的类,子类可以继承他的Annotation!
//但是这个注解只能在类的级别上才能起作用,若是实现接口层次上,不会被继承
public @interface InheritedTest
{
 String value();
}

package com.langsin.annotation;
@InheritedTest("langsin")
public class Parent
{
 public void doSomething()
 {
  System.out.println("hello");
 }
}


package com.langsin.annotation;
public class Child extends Parent
{
 
}


package com.langsin.annotation;
public class Test
{
 public static void main(String[] args)
 {
  Class<Child> c = Child.class;
  
  if(c.isAnnotationPresent(InheritedTest.class))
  {
   InheritedTest inheritedTest = c.getAnnotation(InheritedTest.class);
   String value = inheritedTest.value();
   System.out.println(value);
  }
 }
}

 

 

附:项目组总结的annotation的应用。 Annotation -Junit,Spring,Hibernate应用.rar

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics