java注解

一, 基本内置注解

name 简介
@Override 表示这个方法重写了父类的方法
@Deprecated 表示这个方法已经过期,不建议开发者使用
@SuppressWarnings 这个注解的用处是忽略警告信息。
@SafeVarargs jdk1.7后@SafeVarargs注解只能用在参数长度可变的方法或构造方法上,且方法必须声明为static或final,否则会出现编译错误
@FunctionalInterface @FunctionalInterface这是Java1.8 新增的注解,用于约定函数式接口。

@SuppressWarnings
就对这些警告进行了抑制,即忽略掉这些警告信息。@SuppressWarnings 有常见的值,分别对应如下意思

1.deprecation:使用了不赞成使用的类或方法时的警告(使用@Deprecated使得编译器产生的警告);
2.unchecked:执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型; 关闭编译器警告
3.fallthrough:当 Switch 程序块直接通往下一种情况而没有 Break 时的警告;
4.path:在类路径、源文件路径等中有不存在的路径时的警告;
5.serial:当在可序列化的类上缺少 serialVersionUID 定义时的警告;
6.finally:任何 finally 子句不能正常完成时的警告;
7.rawtypes 泛型类型未指明
8.unused 引用定义了,但是没有被使用
9.all:关于以上所有情况的告。

二, 自定义注解

实现简单的仿spring的@Value注解, 实现变量,方法的赋值

@Value

实现作用于方法的参数和成员变量

@Value.java

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.PARAMETER })
public @interface Value {

	String value() default "";

}

解析使用

JDBCConfig.java

public class JDBCConfig {

	@Value("127.0.0.1")
	private String host;
	@Value("root")
	private String passwd;

    ...

}

使用反射, 获取到成员变量, 在判断改变量是否添加了注解, 添加就赋值

Class<?> clazz = Class.forName("top.itkaoti.annotation.JDBCConfig");
JDBCConfig jdbcConfig = (JDBCConfig) clazz.newInstance();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
	// 判断是否使用了value注解	 
	if (field.isAnnotationPresent(Value.class)) {
		Value annotation = field.getAnnotation(Value.class);
		String value = annotation.value();
		
		// 方法1:直接access为true
		//				if (!field.isAccessible()) {
		//					field.setAccessible(true);
		//				}
		//				field.set(jdbcConfig, value);
		
		// 方法2: 调用set方法
		String name = field.getName();
		Method declaredMethod = clazz.getDeclaredMethod("set" + firstUpCase(name), value.getClass());
		declaredMethod.invoke(jdbcConfig, value);
	}
}
System.out.println(jdbcConfig);

三, 元注解

元注解有这么几种:

@Target 
@Retention 
@Inherited 
@Documented 
@Repeatable (java1.8 新增) 

@Target

@Target 表示这个注解能放在什么位置上, @Value 这个注解上的@Target是:@Target({FIELD,PARAMETER}),表示可以用在变量和方法参数

类型 作用
ElementType.TYPE 能修饰类、接口或枚举类型
ElementType.FIELD 能修饰成员变量
ElementType.METHOD 能修饰方法
ElementType.PARAMETER 能修饰参数
ElementType.CONSTRUCTOR 能修饰构造器
ElementType.LOCAL_VARIABLE 能修饰局部变量
ElementType.ANNOTATION_TYPE 能修饰注解
ElementType.PACKAGE 能修饰包

@Retention

@Retention 表示生命周期 @JDBCConfig 上的值是 RetentionPolicy.RUNTIME, 表示可以在运行的时候依然可以使用。

类型 作用
RetentionPolicy.SOURCE 注解只在源代码中存在,编译成class之后,就没了。@Override 就是这种注解。
RetentionPolicy.CLASS 注解在java文件编程成.class文件后,依然存在,但是运行起来后就没了。@Retention的默认值,即当没有显式指定@Retention的时候,就会是这种类型。
RetentionPolicy.RUNTIME 注解在运行起来之后依然存在,程序可以通过反射获取这些信息,自定义注解@Value 就是这样。

@Inherited

@Inherited 表示该注解具有继承性。如例,设计一个DBUtil的子类,其getConnection2方法,可以获取到父类DBUtil上的注解信息。

@Documented

@Documented 如图所示, 在用javadoc命令生成API文档后,DBUtil的文档里会出现该注解说明。

@Repeatable (java1.8 新增)

当没有@Repeatable修饰的时候,注解在同一个位置,只能出现一次,如例所示:
@Value("127.0.0.1")
@Value("root")
如果对同一个重复使用两次, 那么结果就会报错了。
使用@Repeatable之后,再配合一些其他动作,就可以在同一个地方使用多次了。

参考:

1.注解系列教材

2. 本文的案例源码