今天我继续来介绍java中的注解。注解与接口和类不同的是注解是不允许继承的,但是注解中有一个和继承有关的元注解:@Inherited。如果我们在定义注解时候加上这个元注解那么我们就可以在子类中监测到该注解的存在。
@Target(ElementType.TYPE) @Inherited @Retention(RetentionPolicy.RUNTIME) public @interface Action { boolean isSingle() default true; String value() default ""; String url() default ""; } @Action class BaseController{ } public class UserController extends BaseController{ public static void main(String[] args) { System.out.println(UserController.class.isAnnotationPresent(Action.class)); //true System.out.println(BaseController.class.isAnnotationPresent(Action.class)); //true } }
如上代码所示:我在BaseController上加了Action的注解但是没有在UserController上加但是我却可以在UserController类上检查到Action注解的存在就是因为我们在定义注解时加了@Inherited。
我们现在已经可以自己创建注解,接下来我来给大家介绍如何获取注解的信息。在java中是通过反射来获取注解的信息的,在Class,Method,Field,Constructor中都有如下的这几个方法:getAnnotations()获取所有的注解,getDeclaredAnnotations获取所有声明的注解,忽略inherited来的注解,getAnnotations(Class<A> annotationclass)获取指定类型的注解,isAnnotationPresent(Class<A> annotationclass)判断是否有指定类型的注解。下面我来通过代码来获取类上的注解:
@Target(ElementType.TYPE) @Inherited @Retention(RetentionPolicy.RUNTIME) @interface Action { boolean isSingle() default true; String value() default ""; String url() default ""; } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface Service { String value() default ""; String url() default ""; } @Action(value="action",url="actionurl") @Service(value="service",url="serviceurl") class BaseController{ } public class UserController extends BaseController{ public static void main(String[] args) throws ClassNotFoundException { Class<BaseController> cls = BaseController.class; Annotation[] annotations = cls.getAnnotations(); for (Annotation annotation : annotations) { if(annotation instanceof Action){ Action action = (Action)annotation; System.out.println(action.url()); //actionurl System.out.println(action.value()); //action } if(annotation instanceof Service){ Service service = (Service)annotation; System.out.println(service.url()); //serviceurl System.out.println(service.value()); //service } } } }
在java中Method和Contructor都有方法参数,而参数也是可以有注解的,所以有一个方法返回参数的注解:getParameterAnnotations()返回值是一个二维数组。我们来看一个例子:
public class TestMethodAnnotations { @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) static @interface requestParam { String value(); } @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) static @interface DefaultValue { String value() default ""; } public void test(@requestParam("useranme") String username, @requestParam("password") @DefaultValue("1234") String password){ } public static void main(String[] args) throws NoSuchMethodException, SecurityException { Class<TestMethodAnnotations> cls = TestMethodAnnotations.class; Method method = cls.getMethod("test",new Class[]{String.class,String.class}); Annotation[][] anns = method.getParameterAnnotations(); for (Annotation[] annotations : anns) { for (Annotation annotation : annotations) { if(annotation instanceof requestParam){ requestParam request = (requestParam)annotation; System.out.println(request.value()); } if(annotation instanceof DefaultValue){ DefaultValue defaultValue = (DefaultValue)annotation; System.out.println(defaultValue.value()); } } } } }
代码还是比较的简单的,在这个例子中我们使用@requestParam和@DefaultValue两个注解来修饰方法的参数然后使用getParameterAnnotations这个方法来获取方法参数上的注解。
通过注解我们可以实现很多的功能,比如依赖注入,绑定参数等等,掌握注解的使用有利于我们日常的开发并且为日后学习框架打下基础。