天天看点

自定义注解(二)

之前写过自定义注解的例子,现在看一看,觉得有些东西还没有理解透彻,所以打算再重新整理一些会用得到的知识。

感谢下面这些博客的的分享:

http://blog.csdn.net/yixiaogang109/article/details/7328466

java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作

用。包含在 java.lang.annotation 包中。

1.元注解

元注解是指注解的注解。包括 @Retention @Target @Documented @Inherited四种。

1.1 @Retention 

定义注解的保留策略

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    RetentionPolicy value();
}
           
public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
    SOURCE,//注解仅存在于源码中,在class字节码文件中不包含

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     */
    CLASS,// 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME// 注解会在class字节码文件中存在,在运行时可以通过反射获取到
}
           

1.2 @Target

定义注解的作用目标

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    ElementType[] value();
}
           
public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE, //接口、类、枚举、注解

    /** Field declaration (includes enum constants) */
    FIELD,  //字段、枚举的常量

    /** Method declaration */
    METHOD,  //方法

    /** Parameter declaration */
    PARAMETER, //方法参数

    /** Constructor declaration */
    CONSTRUCTOR, //构造函数

    /** Local variable declaration */
    LOCAL_VARIABLE,//局部变量

    /** Annotation type declaration */
    ANNOTATION_TYPE, //注解

    /** Package declaration */
    PACKAGE //包
}
           

1.3 @Documented

说明该注解将被包含在javadoc中

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
           

1.4 @Inherited

说明子类可以继承父类中的该注解

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
           

2.关于@inherited

上一篇博客,对于@Inherited 没有理解好,在这里又学习了一下

感谢这篇博客的分享:

http://blog.csdn.net/wbchn/article/details/3445541

http://blog.csdn.net/meconsea/article/details/3044816

自定义的注解:

package org.ygy.annotation.lesson02;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Table {
	public String name();
}
           
package org.ygy.annotation.lesson02;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Inherited
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Description {
	public String value() default "nothing";
}
           
package org.ygy.annotation.lesson02;

@Table(name = "t_blog")
public class BlogEntity {
	private Long id;
	private String title;

	@Description("获取ID")
	public Long getId() {
		return id;
	}
	
	public void setId(Long id) {
		this.id = id;
	}

	@Description
	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

}
           
package org.ygy.annotation.lesson02;

public class WordBlogEntity extends BlogEntity {
	private String word;

	public String getWord() {
		return word;
	}

	public void setWord(String word) {
		this.word = word;
	}

}
           
package org.ygy.annotation.lesson02;

public class PictureBlogEntity {

}
           

测试方法:

package org.ygy.annotation.lesson02;

import java.lang.reflect.Method;

public class InheritedTest {
	
	public static <T> boolean validateClassInherited(Class<T> target) {
		if(target.isAnnotationPresent(Table.class)) {
			Table table = target.getAnnotation(Table.class);
			System.out.println(target.getSimpleName() + ":" + table.name());
			return true;
		}
		
		return false;
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static Object validateMehodInherited(Object obj) {
		try {
			Class cls = obj.getClass();
			
			//temp
			Method m = cls.getMethod("getTitle", new Class[]{});
			if(m.isAnnotationPresent(Description.class)) {
				System.out.println("OK. ");
			}
			
			while (cls != null) {
				Method[] methods = cls.getDeclaredMethods();
				
				for(Method method : methods) {
					if(method.isAnnotationPresent(Description.class)) {
						Description desc = method.getAnnotation(Description.class);
						System.out.println(cls.getSimpleName() + "--" + method.getName() + ":" + desc.value());
					}
				}
				
				cls = cls.getSuperclass();
			}
			
		} catch (Exception ex) {
			return null;
		}
		
		return null;
	}
	
	public static void main(String[] args) {
		
		//验证Class上的注解是否可以继承
		if(validateClassInherited(BlogEntity.class)) {
			System.out.println("BlogEntity OK");
		}
		
		if(validateClassInherited(WordBlogEntity.class)) {
			System.out.println("WordBlogEntity OK");
		}
		
		if(validateClassInherited(PictureBlogEntity.class)) {
			System.out.println("wrong");
		}
		
		//验证方法上的注解是否可以继承
		validateMehodInherited(new BlogEntity());
		
		validateMehodInherited(new WordBlogEntity());
		
	}
}
           

通过上面的测试,可以总结出:

在注解上添加@Inherited注解,则该注解可以被继承,上面测试了标注在类上,和方法上

只要子类没有重写父类的方法,或者实现父类的抽象方法,在子类中,是可以被继承的。

自定义注解系列:

自定义注解(一)

自定义注解(二)

继续阅读