基础技能之注解

定义

  • 也叫作元数据。一种代码级别的说明。他是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以生命在包、类、字段、方法、局部变量、方法参数等的前面,用于对这些元素进行说明,注释。

作用的分类

  • 编写文档:通过代码里标识的元数据生成文档
  • 代码分析:通过代码里标识的元数据对代码进行分析
  • 编译检查:通过代码里标识的元数据让编译器能够实现基本的编译检查

如何定义一个注解

    示例如下

@interface 注解名称{

}

  

一、可以为其添加相应的参数,参数的定义为:【类型  参数名称()  default  属性值】或者【类型  参数名称()】。如果没有为参数定义默认值,则使用该注解时,此参数为必填项。

 

@interface Style{
	String background() default "blue"; //设置默认值
	int fontSize() ;  //没有设置默认值,则使用本注解时,该参数必填
	String[] padding() default {"0"};
	enum Color{ BULE,RED,GREEN};
	boolean gnore() default false;
}

@Style(fontSize=1)
class Table{	
	
}

public class ZhujieTest {

	public static void main(String[] args) {
	Method m;
	try {
                 //获取方法上的注解。获取字段、类的注解的方式和获取方式的注解方式类似。 
		m = Table.class.getMethod("a",null);
		System.out.println(m);
		System.out.println(m.getDeclaredAnnotations().length);
		System.out.println(m.getAnnotations().length);		
		System.out.println(m.getAnnotation(Style.class));//获取指定的注解

	} catch (NoSuchMethodException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (SecurityException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}	
	}
}

 

 

 

注解参数可以支持的数据类型:

  1. 所有的基本类型(int,float,boolean,byte,double,char,long,short)
  2. String类型
  3. Class类型
  4. enum类型
  5. Annoatation类型
  6. 以上所有类型的数组

注:基本类型的包装类也不支持。

 

二、4个标准的meta-annotation类型,它们被用来提供对其他annotation类型作说明。它们分别是

  1. @Target  用来说明注解所修饰的对象范围
  2. @Retention  定义了该注解所保留的时间长短
  3. @Documented  用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化
  4. @Inherited  元注解的一个标记注解。该是否能被子类所继承。

@Target,若未使用添加该注解,则使用位置不受限制。其取值(ElementType)如下:

CONSTRUCTOR 用于描述构造器
FIELD 用于描述域
LOCAL_VARIABLE 用于描述局部变量
METHOD 用于描述方法
PACKAGE 用于描述包
PARAMETER 用于描述参数
TYPE 用于描述类、接口(包括注解类型) 或enum声明

 

@Retention,被描述的注解在什么范围内失效。其取值(RetentionPoicy)如下

 

SOURCE 在源文件中有效(即源文件保留)
CLASS 在class文件中有效(即class保留)
RUNTIME 在运行时有效(即运行时保留)

 

其关系:RUNTIME 包含CLASS,CLASS 包含SOURCE。

注:若不添加该注解,则默认是保留在class文件内有效。只有设置为RUNTIME,才能通过反射获取到。

 

@Documented

     用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。

 

@Inherited

    是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。

 

注意:@Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,方法并不从它所重载的方法继承annotation。

 

当@Inherited annotation类型标注的annotation的Retention是RetentionPolicy.RUNTIME,则反射API增强了这种继承性。如果我们使用java.lang.reflect去查询一个@Inherited annotation类型的annotation时,反射代码检查将展开工作:检查class和其父类,直到发现指定的annotation类型被发现,或者到达类继承结构的顶层。

 

 

 

总结:若希望通过反射获取注解,请添加  @Retention(RetentionPolicy.RUNTIME);

           若希望指定注解的使用范围,请使用注解@Target,后面指定范围属性;

           若希望类的注解能被子类应用,则使用@Inherited ;方法的注解重载后不能被继承。

           若参数只有一个,则可以将参数名称设置为value;在使用该注解时,参数名称可以忽略不写。如下示例:

     

 

@interface V{
	String value();
}

@interface V2{
	String val();
}

@V("") //可以忽略参数名
@V2(val="") //参数名必填
class CV{
	
	@V(value ="")
	public void v1(){}
}

 

猜你喜欢

转载自ruxia2010.iteye.com/blog/2238190
今日推荐