注解

-- Start

简介

注解有点像修饰符,它可以加在方法、类、参数、包、域等前面提供一些附加信息。之后某些工具就可以通过反射来获得这些注解,从而做一些特殊处理。所以如果你还不熟悉反射,请先学习反射

元注解

所谓元注解指的是定义注解的注解,它们包含在 java.lang.annotation 包中,包含如下元注解。

Documented 指示被修饰的注解包含在javadoc生成的文档中。
Inherited 指示被修饰的注解应用一个类时,该注解可以被它的子类继承。
Native 指示当被修饰的注解修饰一个字段时,该字段可能是一个本地值。
Repeatable 指示被修饰的注解可以重复修饰一个类,字段等
Retention 指示被修饰的注解可以保留多长时间。
Target 指示被修饰的注解可以修饰哪些属性。如:方法,字段等

预定义注解

Java 预定义了如下的注解,它们位于 java.lang 包中。

@Deprecated 表示被修饰的属性不在推荐使用
@Override 用来告诉编译器该属性继承自父类
@SuppressWarnings 用来告诉编译器忽略指定的警告

自定义注解

下面的代码定义了一个名字是 ParaAnnotation 的注解,用@interface 关键字定义注解,该注解定义了 name 属性,格式有点像方法定义。

1. @Target({ ElementType.PARAMETER } 表示该注解用来修饰参数。

2. @Retention(RetentionPolicy.RUNTIME) 表示该注解可以再运行时使用。

package shangbo.junit;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.PARAMETER })
public @interface ParaAnnotation {
	String name() default "";
}

使用注解

如果定义了注解而没有工具使用它,那么该注解没有任何意义。下面的例子演示了一个用注解自动测试代码的例子。

1. 被测试类

package shangbo.junit;

public class StringUtils {

	public String trimToEmpty(@ParaAnnotation(name = "trimToEmpty.input") String str) {
		if (str == null) {
			return "";
		}

		return str.trim();
	}

	public String trimToNull(@ParaAnnotation(name = "trimToNull.input") String str) {
		if (str == null) {
			return null;
		}

		str = str.trim();
		if (str.equals("")) {
			return null;
		}

		return str;
	}
}

2. 测试类

package shangbo.junit;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.Map;

public class Test {
	
	// 此处代码应该配置在 XML 中
	private static Map<String, String> parasMap = new HashMap<String, String>();
	static {
		parasMap.put("trimToEmpty.input", "test trimToEmpty");
		parasMap.put("trimToNull.input", "test trimToNull");
	}
	
	@SuppressWarnings("rawtypes")
	public static void main(String[] args) throws Exception {
		// 要测试的类,此处应该通过参数传递
		Class testClass = StringUtils.class;
		
		// 通过反射创建对象
		Object testObject = getInstance(testClass);
		
		// 通过反射调用该类的所有方法
		for (Method m : testClass.getDeclaredMethods()) {
			Object returnValue = m.invoke(testObject, getParameterValues(m.getParameters()));
			System.out.println(returnValue);
		}
	}
	
	@SuppressWarnings("rawtypes")
	private static Object getInstance(Class c) throws Exception {
		// 得到构造方法
		Constructor constructor = getConstructor(c);

		// 得到构造方法的所有参数值
		Object[] paras = getParameterValues(constructor.getParameters());

		// 创建对象并返回
		return constructor.newInstance(paras);
	}
	
	@SuppressWarnings("rawtypes")
	private static Constructor getConstructor(Class c) {
		// 得到所有构造方法
		Constructor[] constructors = c.getDeclaredConstructors();

		// 返回第一个构造方法
		return constructors[0];
	}
	
	private static Object[] getParameterValues(Parameter[] paras) throws Exception {
		if(paras == null || paras.length == 0) {
			return null;
		}
		
		//
		Object[] paraValues = new Object[paras.length];
		for (int i = 0; i < paras.length; i++) {
			paraValues[i] = getParameterValue(paras[i]);
		}
		
		return paraValues;
	}
	
	private static Object getParameterValue(Parameter para) throws Exception{
		// 得到该参数的 ParaAnnotation 注解
		ParaAnnotation parameterAnnotation = para.getAnnotation(ParaAnnotation.class);
		if(parameterAnnotation == null) {
			throw new Exception("No ParaAnnotation found for this Parameter");
		}
		
		// 根据注解得到参数值
		Object parameterValue = parasMap.get(parameterAnnotation.name());
		if(parameterValue == null) {
			throw new Exception("Not found the value by name " + parameterAnnotation.name());
		}
		
		return parameterValue;
	}
}

---更多参见:Java 精萃
-- 声 明:转载请注明出处
-- Last Updated on 2014-08-23
-- Written by ShangBo on 2014-08-22
-- End

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值