首页  »   编程

Java学习系列(二十一)Java面向对象之诠注详解

网友分享于:2015-04-28  浏览:0次
Java学习系列(二十一)Java面向对象之注解详解


转载请注明出处:http://blog.csdn.net/lhy_ycu/article/details/45295947


一、前言


Java中的注解Annotation运用到很多方面,比如之前讲的单元测试中的@Test、Spring、SpringMVC还有其他框架等等。Java本身自带的注解也有一些,比如:@Override(子类要重写/覆写父类的对应方法)、@Deprecated(表示方法不建议被使用)、@SuppressWarnings(抑制警告)等等。当然,我们也可以自定义一些自己需要的注解(通常可以加在包,类,字段,方法,方法的参数以及局部变量上),这需要Java提供的四种元注解来负责完成我们的自定义注解功能。总体来说,注解还是比较简单的。下面先了解一下这四种元注解:


二、四种元注解(来源网络)

(一) @Target
@Target 表示该注解用于什么地方,可取的值包括:
ElemenetType.CONSTRUCTOR       构造器声明
ElemenetType.FIELD            字段声明(包括 enum 实例)
ElemenetType.LOCAL_VARIABLE     局部变量声明
ElemenetType.METHOD       方法声明
ElemenetType.PACKAGE            包声明
ElemenetType.PARAMETER       参数声明
ElemenetType.TYPE         类,接口(包括注解类型)或enum声明
ElementType.ANNOTATION_TYPE     注解
 
(二) @Retention
@Retention 表示在什么级别保存该注解信息。可选的 RetentionPolicy 参数包括:
RetentionPolicy.SOURCE       注解将被编译器丢弃
RetentionPolicy.CLASS        注解在class文件中可用,但会被VM丢弃
RetentionPolicy.RUNTIME       JVM将在运行期也保留注解,因此可以通过反射机制读取注解的信息。

(三) @Documented
@Documented 将此注解包含在 javadoc 中

(四)@Inherited
@Inherited 允许子类继承父类中的注解


三、实例说明

1) 作用在类上的注解
// 编译器将把注解信息记录在class文件中,当运行Java程序时JVM会保留注解,因此可以通过<a target=_blank href="http://blog.csdn.net/lhy_ycu/article/details/45289391">反射</a>机制来读取注解的信息。
@Retention(RetentionPolicy.RUNTIME)
// 注解作用在类上面
@Target(ElementType.TYPE)
public @interface ClassName {
	// 声明默认值
	String name() default "豆豆";

	// 特殊的值
	String value();
}

2) 作用在属性(字段)上的注解
@Retention(RetentionPolicy.RUNTIME)
// 注解作用在属性(字段)上
@Target(ElementType.FIELD)
public @interface FieldName {
	String value();
}

3)作用在方法上的注解
@Retention(RetentionPolicy.RUNTIME)
// 注释作用在方法上
@Target(ElementType.METHOD)
public @interface MethodName {
	String value();

	Class<?> type();
}

4)实例演示

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @author [*昨日重现*] lhy_ycu@163.com
 * @since version 1.0
 * @datetime 2015年4月27日 上午12:57:03
 */

// 指定用的是哪个自定义注解的类,若把name去掉,则name默认为:豆豆
@ClassName(name = "实体", value = "用户")
public class User {
	@FieldName("姓名")
	private String name;
	@FieldName("性别")
	private String sex;

	public String getName() {
		return name;
	}

	@MethodName(type = java.lang.String.class, value = "王五")
	public void setName(String name) {
		this.name = name;
	}

	public String getSex() {
		return sex;
	}

	@MethodName(type = java.lang.String.class, value = "男")
	public void setSex(String sex) {
		this.sex = sex;
	}

	@Override
	public String toString() {
		return "User [name=" + name + ", sex=" + sex + "]";
	}

	public static void main(String[] args) throws Exception {
		Class<?> c1 = Class.forName("com.leo.annotation.User");
		// Class<?> c1 = Student.class;

		// 一: 获取类上的注解信息
		// 如果该元素的指定注解类型的注解存在于此对象上则返回这些注解,否则返回 null
		ClassName cn = c1.getAnnotation(ClassName.class);
		System.out.println(cn.name() + " ," + cn.value());
		System.out.println("\n=============================");

		// 二:获取属性(字段)上的注解信息
		Field f1 = c1.getDeclaredField("sex");
		f1.setAccessible(true);
		FieldName fn = f1.getAnnotation(FieldName.class);
		System.out.println(fn.value());

		// Field[] fields = c1.getDeclaredFields();
		// for (Field field : fields) {
		// field.setAccessible(true);
		// FieldName fn = field.getAnnotation(FieldName.class);
		// if (fn != null) {
		// System.out.println(fn.value());
		// }
		// }

		// 三:获取方法上的注解信息
		Method[] methods = c1.getDeclaredMethods();
		User obj = (User) c1.newInstance();
		for (Method method : methods) {
			System.out.println("方法名:" + method.getName());
			// 检查方法上面是否有Annotation
			MethodName mn = method.getAnnotation(MethodName.class);
			if (mn != null) {
				// 回调赋值。第一个参数为目标对象,第二个参数为被访问的方法实参
				method.invoke(obj, mn.value());
			}
		}
		System.out.println(obj.getName() + " ," + obj.getSex());
	}

}

四、总结

1)注意:注解不是注释。注解是实现程序功能的重要组成部分,而注释提供代码功能的说明。

2)注解使得Java源代码中不但可以包含功能性的实现代码,还可以添加元数据。


相关解决方案

最新解决方案