Java子类是否能继承父类上的注解

您所在的位置:网站首页 父类方法 Java子类是否能继承父类上的注解

Java子类是否能继承父类上的注解

#Java子类是否能继承父类上的注解| 来源: 网络整理| 查看: 265

子类可以继承到父类上的注解吗?

在编写自定义注解时,可以通过指定@Inherited注解,申明自定义注解是否可以被继承;@Inherited只能实现类上的注解继承。

实现情况可细分为以下几种 未申明@Inherited 申明了@Inherited 子类的类上能否继承到父类的类上的注解? × √ 子类实现了父类上的抽象方法,这个方法能否继承到注解? × × 子类继承了父类上的方法,这个方法能否继承到注解? √ √ 子类重写了父类上的方法,这个方法能否继承到注解? × ×

spring的注解,即便该注解没有被继承到子类上,但子类同样能享有这个注解带来的效果,这可能和spring的注解扫描和bean加载机制有关。

代码示例 自定义注解 package test.annotation; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; /** * 自定义注解 */ @Inherited //申明注解可以被继承 @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) //可以通过反射读取注解 public @interface MyAnnotation { String value(); } 父类 package test.annotation; @MyAnnotation(value = "类名上的注解") public abstract class ParentClass { @MyAnnotation(value = "父类的abstractMethod方法") public abstract void abstractMethod(); @MyAnnotation(value = "父类的doExtends方法") public void doExtends() { System.out.println(" ParentClass doExtends ..."); } @MyAnnotation(value = "父类的doHandle方法") public void doHandle(){ System.out.println(" ParentClass doHandle ..."); } } 子类 package test.annotation; public class SubClass extends ParentClass{ //子类实现父类的抽象方法 @Override public void abstractMethod() { System.out.println("子类实现父类的abstractMethod抽象方法"); } //子类继承父类的doExtends方法,直接调用父类方法 //子类重写父类的doHandle方法 @Override public void doHandle(){ System.out.println("子类覆盖父类的doHandle方法"); } } 测试类 package test.annotation; import java.lang.reflect.Method; public class MainTest { public static void main(String[] args) throws SecurityException,NoSuchMethodException { Class clazz = SubClass.class; if (clazz.isAnnotationPresent(MyAnnotation.class)) { MyAnnotation cla = clazz.getAnnotation(MyAnnotation.class); System.out.println("子类继承到父类类上Annotation,其信息如下:"+cla.value()); } else { System.out.println("子类没有继承到父类类上Annotation"); } // 实现抽象方法测试 Method method = clazz.getMethod("abstractMethod", new Class[] {}); if (method.isAnnotationPresent(MyAnnotation.class)) { MyAnnotation ma = method.getAnnotation(MyAnnotation.class); System.out.println("子类实现父类的abstractMethod抽象方法,继承到父类抽象方法中的Annotation,其信息如下:"+ma.value()); } else { System.out.println("子类实现父类的abstractMethod抽象方法,没有继承到父类抽象方法中的Annotation"); } //重写测试 Method methodOverride = clazz.getMethod("doExtends", new Class[] {}); if (methodOverride.isAnnotationPresent(MyAnnotation.class)) { MyAnnotation ma = methodOverride.getAnnotation(MyAnnotation.class); System.out.println("子类继承父类的doExtends方法,继承到父类doExtends方法中的Annotation,其信息如下:"+ma.value()); } else { System.out.println("子类继承父类的doExtends方法,没有继承到父类doExtends方法中的Annotation"); } //继承测试 Method method3 = clazz.getMethod("doHandle", new Class[] {}); if (method3.isAnnotationPresent(MyAnnotation.class)) { MyAnnotation ma = method3.getAnnotation(MyAnnotation.class); System.out.println("子类覆盖父类的doHandle方法,继承到父类doHandle方法中的Annotation,其信息如下:"+ma.value()); } else { System.out.println("子类覆盖父类的doHandle方法,没有继承到父类doHandle方法中的Annotation"); } } }

编写自定义注解时未申明@Inherited的运行结果: 子类没有继承到父类类上Annotation 子类实现父类的abstractMethod抽象方法,没有继承到父类抽象方法中的Annotation 子类继承父类的doExtends方法,继承到父类doExtends方法中的Annotation,其信息如下:父类的doExtends方法 子类覆盖父类的doHandle方法,没有继承到父类doHandle方法中的Annotation

编写自定义注解时申明了@Inherited的运行结果: 子类继承到父类类上Annotation,其信息如下:类名上的注解 子类实现父类的abstractMethod抽象方法,没有继承到父类抽象方法中的Annotation 子类继承父类的doExtends方法,继承到父类doExtends方法中的Annotation,其信息如下:父类的doExtends方法 子类覆盖父类的doHandle方法,没有继承到父类doHandle方法中的Annotation

重写方法如何实现继承注解?

@Inherited只能实现类上的注解继承;要想实现重写父类方法上注解的继承,可以通过反射在继承链上找到方法上的注解,但实现很繁琐,还需要考虑桥接方法。 幸好Spring提供了AnnotatedElementUtils类,来方便我们处理注解的继承问题。

// spring提供的工具类 AnnotatedElementUtils MyAnnotation annotation = AnnotatedElementUtils.getMergedAnnotation(SubClass.class.getMethod("doHandle"), MyAnnotation.class);

调用AnnotatedElementUtils的findMergedAnnotation()方法,可以帮助我们找到父类和接口、父类方法和接口方法上的注解,实现一键找到继承链的注解。

@RequestMapping注解能否被继承?

经过测试,发现子类如果重写了父类的方法,确实不能继承被重写方法的注解,但是子类却可以享有父类中该注解带来的效果。

试了一下spring的注解,即便该注解没有被继承到子类上,但子类同样能享有这个注解带来的效果,这可能和spring的注解扫描和bean加载机制有关。

代码示例 public abstract class AbstractParent { @PostConstruct protected void init() { System.out.println("AbstractParent的init方法"); } } @Component public class Child extends AbstractParent{ @Override protected void init() { System.out.println("Child的init方法"); } @PostConstruct private void init1() { System.out.println("Child的init1方法"); } }

启动后输出: image 如果没有重写,子类@PostConstruct方法执行前会先执行父类@PostConstruct方法。

注解的合并使用 合并注解的含义 注解只在springboot中有用 注解本身并不能被注解继承 注解合并需要使用:@AliasFor 合并注解的案例 @RestController = @Controller + @ResponseBody

把多个注解合并成1个,这里把@RestController和@RequestMapping合并为一个@PathRestController

import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.core.annotation.AliasFor; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @RestController @RequestMapping public @interface PathRestController { @AliasFor("path") String[] value()default {}; @AliasFor("value") String[] path()default {}; } 自定义注解使用场景

自定义注解+拦截器或者AOP切面编程,使用自定义注解来设计框架,使得代码看起来非常优雅。

常见使用场景: 接口使用自定义注解+拦截器,实现登录校验 接口使用自定义注解+AOP,实现记录操作日志 接口使用自定义注解,实现控制请求限流和防止表单重复提交 实体类使用自定义注解,实现校验字段唯一性 实体类字段使用自定义注解,实现数据脱敏



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3