注解(Annotation),也叫元数据。一种代码级别的说明。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释,解释或提示。能提高程序代码的可读性,以便于以后的参考、修改。注释是解释性文本,在运行程序时,会被程序跳过,不做处理。
1、生成文档。这是最常见的,也是Java 最早提供的注解。常用的有@see @param @return 等。
2、跟踪代码依赖性,实现替代配置文件功能。比较常见的是spring 2.5 开始的基于注解配置。作用就是减少配置。现在的框架基本都使用了这种配置来减少配置文件的数量。以后java的程序开发,最多的也将实现注解配置,具有很大用处。
3、在编译时进行格式检查。如@override 放在方法前,如果你这个方法并不是覆盖了超类方法,则编译时就能检查出。
public @interface 注解的名字 {
变量的类型 变量的名字();
变量的类型 变量的名字() default 默认值;
}
1、如果注解中只有一个变量需要赋值,并且这个变量的名字叫value,'value= '可以省略,直接写值。
2、如果注解是数组类型,并且只赋值一个值,{}可以省略;如果赋值多个,则必须使用{......}。
3、如果注解中有多个变量,且没有默认值,使用时,必须全部赋值;如果有默认值,使用时,有默认值可以赋值,也可以不赋值。
1、常见注解
a) @Override,表示当前的方法定义将覆盖超类中的方法。
b)@Deprecated,使用了注解为它的元素编译器将发出警告,因为注解@Deprecated是不赞成使用的代码,被弃用的代码。
c) @SuppressWarnings,关闭不当编译器警告信息。
i.deprecation,使用了过时的类戒方法时的警告。
ii.unchecked,执行了未检查的转换时的警告。
iii.fallthrough,当 Switch 程序块直接通往下一种情况而没有 Break 时的警告等等。
2、编写文档:通过代码里标识的元数据生成文档【生成文档doc文档】
a) @Param 注释的时候使用,在其它地方调用时有提示。

b) @Documented 让注解在导出的文档中显示。
首先看怎么导出文档:选中要导出成文档的项目->project->Generate Javadoc…

单击next->next->finish。
当在注解的前面加上@Documented,该注解就会生成在文档中。

导出文档,如果乱码: javadoc -encoding UTF-8 -charset UTF-8。
3、代码分析:通过代码里标识的元数据对代码进行分析【使用反射】
c) @Target,限定注解可以放的位置。
@Target(
{
TYPE, 放在类的头部
FIELD, 放在字段的头部
METHOD, 放在方法的头部
PARAMETER, 放在参数的头部
CONSTRUCTOR, 放在构造器的头部
LOCAL_VARIABLE 放在局部变量的头部
}
)
d)@Retention,限定注解的生命周期。source(只在java源码时候有效,编译之后失效),class(只在编译时有效),runtime(运行时有效,最常用的)。
e) 自定义一些功能注解。
示例:
package cn.com.javazysq.test1;
/**
* 自定义注解
* 这个注解里有三个变量,其中id已经有默认值了
*/
public @interface MyAnnotation {
//private int id() default 110; 错误的,only public & abstract are permitted
int id() default 110;
String name() default 'abc';
float value();
}
package cn.com.javazysq.test1;
/**
* 自定义注解
*/
public @interface MyAnnotation2 {
int id() default 110;
String name() default 'abc';
float[] value();
}
package cn.com.javazysq.test1;
/**
* 自定义注解
*/
public @interface MyAnnotation3 {
int id() default 110;
String name() default 'abc';
Sex[] value();
}
package cn.com.javazysq.test1;
/**
* 自定义注解
* 只能放在方法的头部
* 只有在运行的时候才有效果
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation4 {
int id() default 110;
}
package cn.com.javazysq.test1;
public enum Sex {
男,女
}
//测试@Param...
package cn.com.javazysq.test1;
public class AnnotationTest {
public static void main(String[] args) {
User u= new User(1, '');
u.sum(1, 2);
}
}
package cn.com.javazysq.test1;
@MyAnnotation(name='张三',value = 59.9F)
public class User {
@MyAnnotation(name='张三',value = 59.9F)
private int id;
private String name;
public int getId() {
return id;
}
@MyAnnotation(59.9F)
@MyAnnotation2(value={1,2,3})
@MyAnnotation3(Sex.女)
@MyAnnotation4()
public void setId(int id) {
this.id = id;
}
@MyAnnotation2(1)
public String getName() {
return name;
}
@MyAnnotation3(value={Sex.女,Sex.男})
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return super.toString();
}
/**
* 构造方法
* @param id 编号
* @param name 名字
*/
public User(int id, String name) {
this.id = id;
this.name = name;
}
/**
* 求和
* @param a 数字1
* @param b 数字2
* @return 两个数字的和
*/
public int sum(int a,int b){
return a+b;
}
}
登陆案例,见代码:
package cn.com.javazysq.test2;
/**
* 自定义注解
* 限定:
* 1.只能放在方法的头部
* 2.只能在运行时有效
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginAnnotation {
String name();
String pwd();
}
package cn.com.javazysq.test2;
public class UserService {
@LoginAnnotation(name='bochy',pwd='123dd')
public boolean login(String name,String pwd){
if('bochy'.equals(name)&&'123'.equals(pwd)){
return true;
}else{
return false;
}
}
}
package cn.com.javazysq.test2;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) throws Exception {
String className='cn.com.bochy.test2.UserService';
String methodName = 'login';
/*获取运行时对象*/
Class c = Class.forName(className);
/*调用无参的构造方法实例化对象*/
Object obj = c.newInstance();
/*获取方法对象*/
Method m = c.getMethod(methodName, String.class,String.class);
//获取注解
LoginAnnotation loginAnnotation = m.getAnnotation(LoginAnnotation.class);
if(loginAnnotation==null){
System.out.println('没有找到注解');
return;
}
//获取注解里的值
String name = loginAnnotation.name();
String pwd = loginAnnotation.pwd();
//调用方法
boolean ret = (boolean) m.invoke(obj, name,pwd);
System.out.println(ret);
}
}