现在很多的开源库都有用到注解,注解的优点我目前了解到的是可以使代码逻辑清晰,编译时就可以查看正确与否,提高效率。
缺点就是增加程序的耦合性。
注解的语法:
@AnnotationTest public void onAnnotationTest() { Log.v(getClass().getName(), "onAnnotationTest"); }
从上述例子中可以看出,通过@xxx来对方法进行注解
定义注解:
从上面大家可以知道通过@AnnotationTest来修饰方法,那么AnnotationTest这个是怎么来的呢?下面我们就开始介绍怎么创建注解了。
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD}) public @interface AnnotationTest { AnnotationTestType type() default AnnotationTestType.TYPE_DEFAULT; }
上述是我创建的一个注解类,可以看出定义注解看起来和定义接口差不多,只不过在interface的前面加一个@修饰就可以了。
当然了,定义注解必不可少的就是用到一些元注解了。元注解的作用就是负责注解其他注解。
Java 5.0定义的元注解有以下几种:
1、@Target 表示该注解可以用于什么地方
ElemType参数包括:
TYPE, 类、接口或者enum声明
FIELD, 域声明(包括enum)
METHOD, 方法声明
PARAMETER, 参数声明
CONSTRUCTOR, 构造器声明
LOCAL_VARIABLE, 局部变量声明
ANNOTATION_TYPE, 注解声明
PACKAGE, 包声明(Java 8特性)
TYPE_PARAMETER, 类型参数声明(Java 8)
TYPE_USE
2、@Retention 表示需要在什么级别保存该注解信息
SOURCE, 注解将被编译器丢弃
CLASS, 注解在class文件中可用,但会被VM丢弃
RUNTIME,VM将在运行期也保留注解,因此可以通过反射机制读取注解信息
3、@Documented 将此注解包含在Javadoc中
4、@Inherit 允许子类继承父类中的注解
通过反射调用注解
这里我们就直接上代码了
1、首先通过反射拿到当前对象中含有@AnnotationTest的方法 public void register(Object object) { if(object == null) { throw new RuntimeException("AnnotationRegister init Object Can't be null"); } Method[] methods = object.getClass().getMethods(); List<AnnotationInfo> methods1 = METHOD_CACHE.get(object.getClass()); if(methods1 == null) { methods1 = new ArrayList<>(); METHOD_CACHE.put(object.getClass(), methods1); for(Method method : methods) { AnnotationTest annotationTest = method.getAnnotation(AnnotationTest.class); if(annotationTest != null) { int modifiers = method.getModifiers(); if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) { AnnotationInfo info = new AnnotationInfo(); info.method = method; info.o = object; info.type = annotationTest.type(); methods1.add(info); } } } } }
2、然后就可以调用具体的方法了 public void post(Object o) { Iterator<Map.Entry<Class<?>, List<AnnotationInfo>>> iterator = METHOD_CACHE.entrySet().iterator(); if(iterator != null) { while (iterator.hasNext()) { Map.Entry<Class<?>, List<AnnotationInfo>> entry = iterator.next(); List<AnnotationInfo> methods = entry.getValue(); if(methods != null) { for(AnnotationInfo method : methods) { if(method.type == AnnotationTestType.TYPE_ADD || method.type == AnnotationTestType.TYPE_MINUS) { try { method.method.invoke(method.o, o); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } } } } } }