-- Start
注解有点像修饰符,它可以加在方法、类、参数、包、域等前面提供一些附加信息。之后某些工具就可以通过反射来获得这些注解,从而做一些特殊处理。所以如果你还不熟悉反射,请先学习反射。
所谓元注解指的是定义注解的注解,它们包含在 java.lang.annotation 包中,包含如下元注解。
Documented | 指示被修饰的注解包含在javadoc生成的文档中。 |
Inherited | 指示被修饰的注解应用一个类时,该注解可以被它的子类继承。 |
Native | 指示当被修饰的注解修饰一个字段时,该字段可能是一个本地值。 |
Repeatable | 指示被修饰的注解可以重复修饰一个类,字段等 |
Retention | 指示被修饰的注解可以保留多长时间。 |
Target | 指示被修饰的注解可以修饰哪些属性。如:方法,字段等 |
@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; } }
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