一、概念:
Annotation它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。更通俗的意思是为程序的元素(类、方法、成员变量)加上更直观更明了的说明,这些说明信息是与程序的业务逻辑无关,并且是供指定的工具或框架使用的。Annontation像一种修饰符一样,应用于包、类型、构造方法、方法、成员变量、参数及本地变量的声明语句中。
二、原理:
Annotation其实是一种接口。通过Java的反射机制相关的API来访问annotation信息。
相关类(框架或工具中的类)根据这些信息来决定如何使用该程序元素或改变它们的行为。annotation是不会影响程序代码的执行,无论annotation怎么变化,代码都始终如一地执行。annotation是不会影响程序代码的执行,无论annotation怎么变化,代码都始终如一地执行。
Annotation与interface的异同:
1)、Annotation类型使用关键字@interface而不是interface。
2)、Annotation类型、方法定义是独特的、受限制的。
Annotation 类型的方法必须声明为无参数、无异常抛出的。这些方法定义了annotation的成员:方法名成为了成员名,而方法返回值成为了成员的类型。而方法返回值类型必须为primitive类型、Class类型、枚举类型、annotation类型或者由前面类型之一作为元素的一维数组。方法的后面可以使用 default和一个默认数值来声明成员的默认值,null不能作为成员默认值,这与我们在非annotation类型中定义方法有很大不同。
Annotation类型和它的方法不能使用annotation类型的参数、成员不能是generic。只有返回值类型是Class的方法可以在annotation类型中使用generic,因为此方法能够用类转换将各种类型转换为Class。
3)、Annotation类型又与接口有着近似之处。
它们可以定义常量、静态成员类型(比如枚举类型定义)。Annotation类型也可以如接口一般被实现或者继承。
三、应用场合
annotation一般作为一种辅助途径,应用在软件框架或工具中,在这些工具类中根据不同的 annontation注解信息采取不同的处理过程或改变相应程序元素(类、方法及成员变量等)的行为。
例如:Junit、Struts、Spring等流行工具框架中均广泛使用了annontion。使代码的灵活性大提高。
四、基本语法:
Java目前包括三种标准注解和四种元注解。元注解主要负责注解其他注解的。
三种标准注解:
@Override,表示当前的方法定义覆盖了父类中的方法。必须要有相同的方法签名即(方法名,参数类型,参数顺序,参数个数)都一样。否则在编译过程中发出错误提示。
@Deprecated,对不应该再使用的方法添加注解,当使用这个方法的时候,会在编译时候显示提示信息。
@SuppressWarnings,关闭不当的编译器报警信息
四种元注解:
@Target,表示该注解可以用什么地方。
TYPE : 类、接口或enum声明
FIELD: 域(属性)声明
METHOD: 方法声明
PARAMETER: 参数声明
CONSTRUCTOR: 构造方法声明
LOCAL_VARIABLE:局部变量声明
ANNOTATION_TYPE:注释类型声明
PACKAGE: 包声明
@Retention,表示需要在什么级别保存该注解信息。
1. SOURCE//按照规定使用注释,但是并不将它保留到编译后的类文件中
2. CLASS//将注释保留在编译后的类文件中,但是在运行时忽略它
3. RUNTIME//将注释保留在编译后的类文件中,并在第一次加载类时读取它
@Documented,将此注解包含到Javadoc中。
@Inherited,允许子类继承父类的注解。
五、自定义Annocation
先看一个简单的annocation
|
package com.cts.elt.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE )//此注解用在类上面
@Retention(RetentionPolicy.RUNTIME)//将注释保留在编译后的类文件中,并在第一次加载类时读取它
@Documented
public @interface MyAnnotation1 {
String value();
}
|
上面这个MyAnnotation1.class文件包含一个值,下面来一个含有两个值的annotation:
|
package com.cts.elt.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;
@Target(ElementType.METHOD )
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation2 {
String description();
boolean isAnnotation();
}
|
关键是来看这两个自定义annotation的用法:
|
package com.cts.elt.annotation;
@MyAnnotation1 ("this
isannotation1" )
public class AnnotationDemo
{
@MyAnnotation2(description
= "this is annotation2", isAnnotation = true)
public void sayHello()
{
System. out.println( "hello
world!");
}
}
|
如果把@MyAnnotation1与@MyAnnotation2的位置换一换,会怎么样?(肯定报错啦!)
六、自定义Annocation高级篇
情景设计:设有一CLASS叫Student,其中有三个fields:
|
private String name = ""; private int age = 0; private String studentId = ""; |
相应的每一个field有一对的set, get方法。 然后我在每个set方法上造一个annotation叫ValueBind的注解,其作用是: 只要set方法上带有ValueBind注解,它就会根据这个字段的类型把一个默认值,自动赋给Student类中相对应的field。
1、先来看一下Student类:
|
package com.cts.elt.annotation;
import java.io.Serializable;
import com.cts.elt.annotation.ValueBind.fieldType;
public class Student implements Serializable
{
private String
name = "";
public String
getName() {
return name;
}
@ValueBind(type
= fieldType.STRING, value = "aa")
public void setName(String
name) {
this.name
= name;
}
public int getAge()
{
return age;
}
@ValueBind(type
= fieldType.INT, value = "30")
public void setAge( int age)
{
this.age
= age;
}
public String
getStudentId() {
return studentId;
}
@ValueBind(type
= fieldType.STRING, value = "101")
public void setStudentId(String
studentId) {
this.studentId
= studentId;
}
private int age
= 0;
private String
studentId = "";
}
|
2、自定义一个ValueBind的Annocation:
|
package com.cts.elt.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;
@Target(ElementType.METHOD )
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ValueBind {
enum fieldType
{
STRING, INT
};
fieldType type();
String value();
}
|
首先这个annotation只能被标注在方法上;其次它含有两个值,一个是enum类型,一个是String类型
3、利用Java类反射机制来实现我们的Annocation:
|
package com.cts.elt.annotation;
import java.lang.reflect.*;
public class PersistStudent
{
public static void main(String[]
args) throws Exception {
Object c = Class.forName("com.cts.elt.annotation.Student").newInstance();
try {
Method[] methodArray = c.getClass().getDeclaredMethods();
for ( int i
= 0; i < methodArray. length; i++) {
if (methodArray[i].isAnnotationPresent( ValueBind. class))
{//如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。
ValueBind annotation
= methodArray[i].getAnnotation(ValueBind .class);//如果存在该元素的指定类型的注释,则返回这些注释,否则返回
null。
String type = String.valueOf(annotation.type());
String value = annotation.value();
if (type.equals( "INT"))
{
methodArray[i].invoke(c, new Integer[]
{ new Integer(value) });
} else {
methodArray[i].invoke(c, new String[]
{ value });
}
}
}
Student annotaedStudent = (Student) c;
System. out.println( "studentId====" +
annotaedStudent.getStudentId()
+ " studentnName====" +
annotaedStudent.getName()
+ " student Age====" +
annotaedStudent.getAge());
} catch (Exception
e) {
throw new Exception(e);
}
}
}
|
运行结果显示:
| studentId====101 studentnName====aa studentAge====30 |
本文深入讲解Java注解的概念、原理及其应用场合,并通过实例演示如何自定义注解及利用反射机制实现注解的功能。

被折叠的 条评论
为什么被折叠?



