- package diyDescription;
- 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;
- @Target({ElementType.METHOD,ElementType.TYPE})
- @Retention(RetentionPolicy.RUNTIME)
- @Inherited
- @Documented
- public @interface Description { //使用@interface关键字定义注解
- //成员以无参数无异常方式声明
- String desc();
- /* String desc(int a);
- * String desc() throws Exception;
- * 都是错误的声明方式
- */
- String author();
- // String author() default ""; 合法的声明
- //可以用default为成员指定一个默认值
- int age() default 18;
- /*
- * 如果声明:Map map(); 则会报错:
- * Invalid type Map for the annotation attribute Description.map;
- * only primitive type, String, Class, annotation, enumeration
- * are permitted or 1-dimensional arrays thereof
- *
- * 只有原始类型和String, Class, annotation, enumeration才可以
- */
- }
- package jtzeng;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Target;
- @Target({ElementType.TYPE})
- public @interface SingleValue1 {
- String desc();
- }
- package jtzeng;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Target;
- @Target({ElementType.METHOD})
- public @interface SingleValue2 {
- String value();
- }
- package jtzeng;
- @SingleValue1( desc = "这是TYPE注解" ) //使用时需指明成员名和赋值号"="
- public class Test {
- @SingleValue2("这是METHOD注解") //使用时可以忽略成员名和赋值号“=”
- public void print() {
- System.out.println();
- }
- }
2.元注解
2.1. @Target
ElemenetType.FIELD --------------------------------------域声明(包括 enum 实例)
ElemenetType.LOCAL_VARIABLE------------------------- 局部变量声明
ElemenetType.METHOD ----------------------------------方法声明
ElemenetType.PACKAGE --------------------------------- 包声明
ElemenetType.PARAMETER ------------------------------参数声明
ElemenetType.TYPE--------------------------------------- 类,接口(包括注解类型)或enum声明
- package jtzeng;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Target;
- @Target({ElementType.TYPE,ElementType.FIELD})
- public @interface Description {
- String desc();
- String author();
- int age() default 21;
- }
2.2. @Retention
RetentionPolicy.CLASS-----------------------------编译时会记录到class中,运行时忽略
RetentionPolicy.RUNTIME------------------------- 运行时存在,可以通过反射读取
- package jtzeng;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- @Retention(RetentionPolicy.RUNTIME) //运行时存在,可以通过反射读取
- //@Retention(RetentionPolicy.SOURCE) //只在源码显示,编译时会丢失
- //@Retention(RetentionPolicy.CLASS) //编译时会记录到class中,运行时忽略
- public @interface Description {
- String desc();
- String author() default "JTZeng";
- int age() default 21;
- }
2.3. @Inherited
- package jtzeng;
- import java.lang.annotation.Inherited;
- @Inherited
- public @interface Description {
- String desc();
- String author() default "JTZeng";
- int age() default 21;
- }
2.4. @Documented
- /*
- * 测试@Documented的功能
- */
- package jtzeng;
- 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;
- @Target({ElementType.METHOD,ElementType.TYPE})
- @Retention(RetentionPolicy.RUNTIME)
- @Inherited
- @Documented
- public @interface Description {
- String desc();
- String author() default "JTZeng";
- int age() default 21;
- }
- /*
- * 定义一个Test测试类,类和方法都有注解
- */
- package jtzeng;
- @Description(desc="这是TYPE注解",author="JTZeng",age=21)
- public class Test {
- private String field = "自定义注解";
- @Description(desc="这是METHOD注解",author="JTZeng",age=21)
- public void print() {
- System.out.println(field);
- }
- }
自定义注解:
使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@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",后加小括号.例:下面的例子FruitName注解就只有一个参数成员。
简单的自定义注解和使用注解实例:
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{ BULE,RED,GREEN};
/**
* 颜色属性
* @return
*/
Color fruitColor() default Color.GREEN;
}
package annotation;
import annotation.FruitColor.Color;
public class Apple {
@FruitName("Apple")
private String appleName;
@FruitColor(fruitColor=Color.RED)
private String appleColor;
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 displayName(){
System.out.println("水果的名字是:苹果");
}
}
注解元素的默认值:
注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为null。因此, 使用空字符串或0作为默认值是一种常用的做法。这个约束使得处理器很难表现一个元素的存在或缺失的状态,因为每个注解的声明中,所有元素都存在,并且都具有相应的值,为了绕开这个约束,我们只能定义一些特殊的值,例如空字符串或者负数,一次表示某个元素不存在,在定义注解时,这已经成为一个习惯用法。例如:
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 FruitProvider {
/**
* 供应商编号
* @return
*/
public int id() default -1;
/**
* 供应商名称
* @return
*/
public String name() default "";
/**
* 供应商地址
* @return
*/
public String address() default "";
}
定义了注解,并在需要的时候给相关类,类属性加上注解信息,如果没有响应的注解信息处理流程,注解可以说是没有实用价值。如何让注解真真的发挥作用,主要就在于注解处理方法,下一步我们将学习注解信息的获取和处理!
二、注解的使用:
第一步:新建一个annotation,名字为:MyAnnotation.java。
package com.dragon.test.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by gmq on 2015/9/10.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation
{
String hello () default "hello";
String world();
}
第二步:建立一个MyTest.java 来使用上面的annotation。
package com.dragon.test.annotation;
/**
* Created by gmq on 2015/9/10.
*/
public class MyTest
{
@MyAnnotation(hello = "Hello,Beijing",world = "Hello,world")
public void output() {
System.out.println("method output is running ");
}
}
第三步:用反射机制来调用注解中的内容
package com.dragon.test.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
/**
* 用反射机制来调用注解中的内容
* Created by gmq on 2015/9/10.
*/
public class MyReflection
{
public static void main(String[] args) throws Exception
{
// 获得要调用的类
Class<MyTest> myTestClass = MyTest.class;
// 获得要调用的方法,output是要调用的方法名字,new Class[]{}为所需要的参数。空则不是这种
Method method = myTestClass.getMethod("output", new Class[]{});
// 是否有类型为MyAnnotation的注解
if (method.isAnnotationPresent(MyAnnotation.class))
{
// 获得注解
MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
// 调用注解的内容
System.out.println(annotation.hello());
System.out.println(annotation.world());
}
System.out.println("----------------------------------");
// 获得所有注解。必须是runtime类型的
Annotation[] annotations = method.getAnnotations();
for (Annotation annotation : annotations)
{
// 遍历所有注解的名字
System.out.println(annotation.annotationType().getName());
}
}
}
输出:
Hello,Beijing
Hello,world
----------------------------------
com.dragon.test.annotation.MyAnnotation