目录
一、自定义Annotation
先来看两个自定义注解java文件:
1.JZDesc.java
package sn.test.test6.annotation;
import java.lang.annotation.*;
/**
* 自定义Annotation:JZDesc
*/
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface JZDesc {
public String value();
}
2.JZMethod.java
package sn.test.test6.annotation;
import java.lang.annotation.*;
/**
* 自定义Annotation:JZMethod
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface JZMethod {
String name();
String sex();
int age();
}
看到这里,你可能彻底蒙圈了,一上来就这么晦涩, 可能你有很多疑问,比如:
- @interface是什么意思?和interface关键字有什么关系吗?
- Documented、Target、Retention 是神马东东?
- ElementType、RetentionPolicy又是啥玩意儿?
不要着急,我下面会一一解答。
首先,@interface 也是一个关键字,和interface关键字没有任何关系,仅仅说明要设计Annotation必须要指定类型为@interface
其次,为了更清楚的解释上面(2)(3)东东的作用,不得不先来看看java的几个原生注解
二、Java元注解
1.什么是元注解?
-定义:作用于注解上的注解,白话就是:这些注解操作的对象还是注解。
2.常见的元注解有哪些?
-分类:@Document ,@Target ,@Retention ,@Inherited
3.元注解用来干嘛的?
作用:
1. @Document :目的让这个Annotation类型的信息可以显示在javaAPI说明文档中,如果不添加的话,使用javadoc生成 的接口文档中将没有这个类型生成的任何信息。
2. @Target:作用是指定这个Annotation可以用在哪些元素之上,如果不指定,则是ElementType枚举值的最大范围
3. @Retention:作用是指定这个Annotation的类型信息保留的范围,如果不指定,则是RetentionPolicy枚举值的最大范围
解答了 Documented、Target、Retention 是神马? 这个疑问,那么再来看看第二个疑问:
ElementType、RetentionPolicy又是啥玩意? 要解释这两个问题,那就不得不提一个jar包:java.lang.annotation,具体往下看
三、java.lang.annotation包
java.lang.annotation包中有两个源文件:ElementType.java,RetentionPolicy.java,下面来看下这两个源文件的内容
1.ElementType.java 源文件
public enum ElementType {
TYPE,
FIELD,
METHOD,
PARAMETER,
CONSTRUCTOR,
LOCAL_VARIABLE,
ANNOTATION_TYPE,
PACKAGE
}
ElementType,一个enum类型,用来定义Annotation可以作用哪些元素上,有如下几种:
* 1:TYPE(类型), 是指可以用在Class,Interface,Enum和Annotation类型上
* 2:FIELD(属性),
* 3:METHOD(方法),
* 4:PARAMETER(参数),
* 5:CONSTRUCTOR(构造函数),
* 6:LOCAL_VARIABLE(局部变量),
* 7:ANNOTATION_TYPE,(注解)
* 8:PACKAGE(包)
2.RetentionPolicy 源文件
public enum RetentionPolicy {
SOURCE,
CLASS,
RUNTIME
}
1. SOURCE-代表的是这个Annotation类型的信息只会保留在程序源码里,一旦编译过后,Annotation的信息就会消失,不会出现在.class文件中
2. CLASS-表示这个Annotation类型的信息既保留在程序源码里,又保留在编译后的.class文件中,但是执行时,不会被加载到JVM中
3. RUNTIME-表示这个Annotation类型的信息会分别保留在在源码里、编译好的.class文件中,执行时也会被加载到JVM中
经过上面的讲解,你可能大概了解上文中自定义Annotation文件 JZMethod.java 和JZDesc.java文件的大致内容,那么又有一个疑问,自己一注解{}内部定义的比如 value() 是什么?有什么要注意的地方吗吗?
public @interface JZDesc {
public String value();//参数成员1
}
public @interface JZMethod {
String name();//参数成员1
String sex();//参数成员2
int age();//参数成员3
}
首先,Annotation内部定义的是注解的参数成员,如@Resource(name="aaa",description="方法1"),那么name和description都是@Resource注解的参数成员,参数成员要指定参数的数据类型,如String,int,byte etc,并且可以用public修饰,也可以省略
其次,一般参数成员定义注意项有几点:
1. 只能用public或默认(default)这两个访问权修饰.例如,String value();可以写成 public String value default "";
2. 参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型,String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();value()参数成员就为String类型* * 3.如果只有一个参数成员,最好把参数名称设为"value",后加小括号比如:String value();
ok,上面基本上全部解释了自定义java文件中包含的内容代表的含义,那么既然定义了两个注解文件:JZDesc.java、JZMethod.java,那么该如何应用呢?下面将简单介绍如何将注解作用到其他类上
四、自定义Annotation的使用
1.AnnotationUsage.java Annotation(JZDesc、JZMethod)使用示例
,
package sn.test.test6.annotation;
@JZDesc("这是本教主自定义的一个注解,作用元素Class")
public class AnnotationUsage {
@JZMethod(name = "唐僧",sex = "男",age = 20)
public String man(){
return "这是一个人";
}
@JZMethod(name = "悟空",sex = "男",age = 500)
public String monkey(){
return "这是一只成精的猴子";
}
@JZMethod(name = "沙僧",sex = "男",age = 1000)
public String monster(){
return "这是一个妖怪";
}
}
2.Client.java 客户端Annotation实际测试
package sn.test.test6.annotation;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
public class Client {
public static void main(String [] args) throws ClassNotFoundException {
System.out.println("===开始测试了====");
Class testClass=Class.forName("sn.test.test6.annotation.AnnotationUsage");
Method[] methods=testClass.getMethods();
/**
* 1.获取作用在Class上的JZDesc类型注解
*/
//判断JZDesc注解是否存在
boolean flag=testClass.isAnnotationPresent(JZDesc.class);
//存在
if (flag){
//获取注解-getAnnotation()
JZDesc jzDesc=(JZDesc)testClass.getAnnotation(JZDesc.class);
//获取参数成员
System.out.println("JZDesc参数成员内容获取为:"+jzDesc.value());
}
/**
* 2.获取作用在Method上的JZMethod类型注解
*/
//判断哪些方法用了Name注解,如果用了,加入set中
Set<Method> set = new HashSet<Method>();
for(Method m:methods){
boolean mflag=m.isAnnotationPresent(JZMethod.class);
if (mflag){
set.add(m);
}
}
//一次输出方法注解内容
for (Method m:set){
JZMethod method=(JZMethod)m.getAnnotation(JZMethod.class);
if (method.age()==20){
System.out.println("===人类===");
}
else if(method.age()==500){
System.out.println("===猴子===");
}
else if(method.age()>500){
System.out.println("===妖怪===");
}
System.out.println("外号:"+method.name()+",性别:"+method.sex()+",岁数:"+method.age());
}
System.out.println("===结束====");
}
}
结果输出:
截止到现在,你应该大致了解了Annotation的定义和使用了,当然java也有一些默认的Annotation类型,比如:@Override,@Deprecated,@SuppressWarnings,这里就不一一介绍了,有兴趣的话可以看看相关的资料信息