天天看點

自定義注解(二)

之前寫過自定義注解的例子,現在看一看,覺得有些東西還沒有了解透徹,是以打算再重新整理一些會用得到的知識。

感謝下面這些部落格的的分享:

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注解,則該注解可以被繼承,上面測試了标注在類上,和方法上

隻要子類沒有重寫父類的方法,或者實作父類的抽象方法,在子類中,是可以被繼承的。

自定義注解系列:

自定義注解(一)

自定義注解(二)

繼續閱讀