初识Annotation

注解:
Annotation(注解)是一个接口,可以通过反射来获取制定程序的Annotation对象,通过Annotation对象来获取注解里面的元数据。

Annotation(注解)是JDK5.0之后引入的。就像修饰符一样使用,应用于包、类型、构造方法、方法、成员变量、参数、本地变量的声明。这些信息被储存在Annotation的"name=value"结构中。

注解分类:
根据注解的参数个数:
1:标记注解,一个没有成员的Annotation类型。这种类型只能使用自身的存在来为我们提供信息,比如:@Override

2.单值注解

3.完整注解

根据注解使用的方法和用途分类:
1.JDK内置系统注解

2.元注解

3.自定义注解

系统内置的标准注解
@Override:用于修饰此方法覆盖了府内的方法

@Deprecated:用于修饰已经过时的方法

@SuppressWarnings:用于通知java编译器禁止特定的编译警告

            当annotation只有单一成员,并成员命名为"value="。这时可以省去"value="

SuppressWarnings注解的常见参数值的简单说明:

    1.deprecation:使用了不赞成使用的类或方法时的警告;
    2.unchecked:执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型; 
    3.fallthrough:当 Switch 程序块直接通往下一种情况而没有 Break 时的警告;
    4.path:在类路径、源文件路径等中有不存在的路径时的警告; 
    5.serial:当在可序列化的类上缺少 serialVersionUID 定义时的警告; 
    6.finally:任何 finally 子句不能正常完成时的警告; 

    7.all:关于以上所有情况的警告。

元注解

    负责注解其他注解,Java 5.0定义了4个meta-annotation类型,用来对其他的Annotation类型做说明
java.long.annotation
1.@Target(目标)

修饰的对象范围:packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、
方法参数和本地变量(循环变量、catch参数)

取值(ElmentType)有:
CONSTRUCTOPR:构造器
FIEDL:域
LOCAL_VARIABLE:局部变量
METHOD:方法
PACKAGE:包
PARAMETER:参数
TYPE:类、接口或enum

比如:

@Target(ElementType.TYPE)
	public @interface Table {
	    /**
	     * 数据表名称注解,默认值为类名称
	     * @return
	     */
	    public String tableName() default "className";
	}
@Target(ElementType.FIELD)
	public @interface NoDBColumn {

	}

注解Table 可以用于注解类、接口(包括注解类型) 或enum声明,而注解NoDBColumn仅可用于注解类的成员变量。

2.@Retention(保留)
表示需要在什么级别保存该注释信息,由于描述注解的生命周期

取值(RetentionPolicy)有:
SOURCE:源文件中有效
CLASS:class文件中有效

RUNTIME:运行时有效

@Target(ElementType.FIELD)
	@Retention(RetentionPolicy.RUNTIME)
	public @interface Column {
	    public String name() default "fieldName";
	    public String setFuncName() default "setField";
	    public String getFuncName() default "getField"; 
	    public boolean defaultDBValue() default false;
	}
Column注解的的RetentionPolicy的属性值是RUTIME,这样注解处理器可以通过反射,获取到该注解的属性值,从而去做一些运行时的逻辑处理

3.@Document(文件)

用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,

因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。

@Target(ElementType.FIELD)
	@Retention(RetentionPolicy.RUNTIME)
	@Documented
	public @interface Column {
	    public String name() default "fieldName";
	    public String setFuncName() default "setField";
	    public String getFuncName() default "getField"; 
	    public boolean defaultDBValue() default false;
	}
4.@Inhrited(遗传)
@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类型被发现,或者到达类继承结构的顶层。

/**
	 * 
	 * @author peida
	 *
	 */
	@Inherited
	public @interface Greeting {
	    public enum FontColor{ BULE,RED,GREEN};
	    String name();
	    FontColor fontColor() default FontColor.GREEN;
	}
自定义注解

定义注解时,不能继承其他的注解或接口。@interface 用来声明一个注解, 其中的每一个方法实际上是声明一个配置参数
方法的名称就是参数的名称,返回值类型就是参数的类型(类型只能是:基本类型、Class、String、enum)
可以通过default来声明参数的默认值

格式:public @interface 注解名{定义体}

可支持的数据类型:
1;所有的基本数据类型(int、float、boolean、byte、double、char、long、short)
2;String类型
3;Class类型
4;enum类型
5;Annotation类型
6;以上所有类型的数组

Annotation类型里面的参数该怎么设定: 
  第一,只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型; 
 
  第二,参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和 String,
Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();这里的参数成员就为String;
  

  第三,如果只有一个参数成员,最好把参数名称设为"value",后加小括号。

package annotation;

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

		/**
		 * 水果名称注解
		 * @author peida
		 *
		 */
		@Target(ElementType.FIELD)
		@Retention(RetentionPolicy.RUNTIME)
		@Documented
		public @interface FruitName {
		    String value() default "";
		}


package annotation;

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

		/**
		 * 水果颜色注解
		 * @author peida
		 *
		 */
		@Target(ElementType.FIELD)
		@Retention(RetentionPolicy.RUNTIME)
		@Documented
		public @interface FruitColor {
		    /**
		     * 颜色枚举
		     * @author peida
		     *
		     */
		    public enum Color{ BLUE,RED,GREEN};
		    
		    /**
		     * 颜色属性
		     * @return
		     */
		    Color fruitColor() default Color.GREEN;

		}


/**
		 * 水果供应者注解
		 * @author peida
		 *
		 */
		@Target(ElementType.FIELD)
		@Retention(RetentionPolicy.RUNTIME)
		@Documented
		public @interface FruitProvider {
		    /**
		     * 供应商编号
		     * @return
		     */
		    public int id() default -1;
		    
		    /**
		     * 供应商名称
		     * @return
		     */
		    public String name() default "";
		    
		    /**
		     * 供应商地址
		     * @return
		     */
		    public String address() default "";
		}


package annotation;

		import annotation.FruitColor.Color;

		public class Apple {
		    
		    @FruitName("Apple")
		    private String appleName;
		    
		    @FruitColor(fruitColor=Color.RED)
		    private String appleColor;
		    
		    @FruitProvider(id=1,name="红富士集团",address="陕西省西安市")
		    private String appleProvider;
		    
		    
		    public void setAppleColor(String appleColor) {
			this.appleColor = appleColor;
		    }
		    public String getAppleColor() {
			return appleColor;
		    }
		    
		    
		    public void setAppleName(String appleName) {
			this.appleName = appleName;
		    }
		    public String getAppleName() {
			return appleName;
		    }
		    
		    public void setAppleProvider(String appleProvider) {
			this.appleProvider = appleProvider;
		    }

		    public String getAppleProvider() {
			return appleProvider;
		    }

		    public void displayName(){
			System.out.println("水果的名字是:苹果");
		    }
		}
注解处理器

如果没有注解处理器,那么注解就不会比注释更有用处了。通过反射机制来创建注解处理器

public class FruitInfoUtil {
	    public static void getFruitInfo(Class<?> clazz){
		
		String strFruitName=" 水果名称:";
		String strFruitColor=" 水果颜色:";
		String strFruitProvicer="供应商信息:";
		
		Field[] fields = clazz.getDeclaredFields();
		
		for(Field field :fields){
		    if(field.isAnnotationPresent(FruitName.class)){
			FruitName fruitName = (FruitName) field.getAnnotation(FruitName.class);
			strFruitName=strFruitName+fruitName.value();
			System.out.println(strFruitName);
		    }
		    else if(field.isAnnotationPresent(FruitColor.class)){
			FruitColor fruitColor= (FruitColor) field.getAnnotation(FruitColor.class);
			strFruitColor=strFruitColor+fruitColor.fruitColor().toString();
			System.out.println(strFruitColor);
		    }
		    else if(field.isAnnotationPresent(FruitProvider.class)){
			FruitProvider fruitProvider= (FruitProvider) field.getAnnotation(FruitProvider.class);
			strFruitProvicer=" 供应商编号:"+fruitProvider.id()+" 供应商名称:"+fruitProvider.name()+" 供应商地址:"+fruitProvider.address();
			System.out.println(strFruitProvicer);
		    }
		}
	    }
	}

/***********输出结果***************/

public class FruitRun {

	    /**
	     * @param args
	     */
	    public static void main(String[] args) {
		
		FruitInfoUtil.getFruitInfo(Apple.class);
		
	    }

	}

猜你喜欢

转载自blog.csdn.net/qq_36447701/article/details/80526858