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

在编写自定义注解时,可以通过指定@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<SubClass> 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方法");
}
}

启动后输出:



如果没有重写,子类@PostConstruct方法执行前会先执行父类@PostConstruct方法。

注解的合并使用

合并注解的含义

  1. 注解只在springboot中有用
  2. 注解本身并不能被注解继承
  3. 注解合并需要使用:@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,实现记录操作日志

接口使用自定义注解,实现控制请求限流和防止表单重复提交

实体类使用自定义注解,实现校验字段唯一性

实体类字段使用自定义注解,实现数据脱敏

Java子类是否能继承父类上的注解的更多相关文章

  1. 转:Java中子类是否可以继承父类的static变量和方法而呈现多态特性

    原文地址:Java中子类是否可以继承父类的static变量和方法而呈现多态特性 静态方法 通常,在一个类中定义一个方法为static,那就是说,无需本类的对象即可调用此方法,关于static方法,声明 ...

  2. Java中子类是否可以继承父类的static变量和方法而呈现多态特性

    静态方法 通常,在一个类中定义一个方法为static,那就是说,无需本类的对象即可调用此方法,关于static方法,声明为static的方法有以下几条限制: 它们仅能调用其他的static 方法. 它 ...

  3. @interface __ annotation 子类可以继承到父类上的注解吗--有结论了

    博客分类: Java/J2se   作者:赵磊 博客:http://elf8848.iteye.com 不了解注解基础知识的请先看<JDK 5 Annotation\注解\注释\自定义注解> ...

  4. Java -- 子类使用super调用父类的方法A,A 调用了方法B,子类也override方法B,那么super.A()最终调用到了子类的B方法

    public class SuperClass{ public void printA(){ System.out.print("SuperClass-printA"); prin ...

  5. java 子类不能继承父类的static方法

    先来看一段代码 /** * Created by bjchengpeng on 2018/7/19. */ /**运行结果 * woof * woofaa * * woof * Basenjiaa * ...

  6. Java中子类能继承父类的私有属性吗?

    前段时间去听老师讲课的时候,老师告诉我子类是可以继承父类所有的属性和方法的.当时我是极其疑惑的,因为之前学校考试时这个考点我记得很清楚:子类只能继承父类的非私有属性和方法.老师给我的解释是这样的--先 ...

  7. javascript中子类如何继承父类

    参考阮一峰的文章:http://javascript.ruanyifeng.com/oop/inheritance.html#toc4 function Shape() { this.x = 0; t ...

  8. Net基础篇_学习笔记_第十二天_面向对象继承(父类和子类)

    继承 我们可能会在一些类中,写一些重复的成员,我们可以将这些重复的成员,单独的封装到一个类中,作为这些类的父类.Student.Teacher.Driver 子类  派生类Person         ...

  9. (转)Java:类与继承

    原文地址: http://www.cnblogs.com/dolphin0520/p/3803432.html 对于面向对象的程序设计语言来说,类毫无疑问是其最重要的基础.抽象.封装.继承.多态这四大 ...

  10. Java:类与继承

    Java:类与继承 对于面向对象的程序设计语言来说,类毫无疑问是其最重要的基础.抽象.封装.继承.多态这四大特性都离不开类,只有存在类,才能体现面向对象编程的特点,今天我们就来了解一些类与继承的相关知 ...

随机推荐

  1. Spring Cloud 部署时如何使用 Kubernetes 作为注册中心和配置中心

    一.Spring Cloud 支持的常见注册中心和配置中心. Spring Cloud 自带的注册中心Eureka以及config配置中心 Nacos,支持注册中心和配置中心等,可以参考:https: ...

  2. C语言:实现数组的删除和增加

    /*      删除方法:     如:12  32  56  84  95     用覆盖的方法     若删除第三个,则第四个要覆盖第三个,第五个要覆盖第四个     覆盖完:12  32  84 ...

  3. C语言:学生成绩排名----冒泡排序

    题目: /*     输入10个学生成绩.     计算总分以及平均分数.     求出高于等于平均分的人数.     再按降序(由大到小)排序成绩并输出      */ 用到的冒泡算法代码模板: / ...

  4. 2024-05-22:用go语言,你有一个包含 n 个整数的数组 nums。 每个数组的代价是指该数组中的第一个元素的值。 你的目标是将这个数组划分为三个连续且互不重叠的子数组。 然后,计算这三个子数

    2024-05-22:用go语言,你有一个包含 n 个整数的数组 nums. 每个数组的代价是指该数组中的第一个元素的值. 你的目标是将这个数组划分为三个连续且互不重叠的子数组. 然后,计算这三个子数 ...

  5. MyBatis抛出BindingException异常可能是你忘了配置资源拷贝

    最近博主在搭建Mybatis项目时遇到了一问题,在一切配置妥当后,开始运行测试代码,但是此时控制台无情的抛出了异常: 开始寻找问题根源 咦?难道是我哪里写错,我的第一反应是我的xml配置文件哪里写错了 ...

  6. VMware Workstation安装Ubuntu窗口太小的解决方式

    1.选择菜单中的:虚拟机--------安装VMware-Tools 2.点击DVD图标 3.将压缩文件复制到桌面 4.解压压缩文件 5.进入解压后的目录,执行命令: sudo perl vmware ...

  7. Flutter(七):Flutter混合开发--接入现有原生工程(iOS+Android)

    在上一篇文章Flutter(六):Flutter_Boost接入现有原生工程(iOS+Android)中介绍了Flutter_Boost的接入方法,这一篇将介绍Flutter自带的接入方法. 新建工程 ...

  8. 开源云原生平台对比 KubeSphere vs Rainbond

    最近因为工作需要,需要找一个功能完善的云原生应用平台,经过自己筛选和朋友推荐,剩下 KubeSphere和Rainbond ,这两个产品都是基于 Kubernetes 之上构建的云原生应用平台,功能都 ...

  9. 在 Flask 项目中配置 Session:简明指南

    在 Flask 项目中配置 Session:简明指南 本文介绍如何在 Flask 项目中配置会话 1. Flask 内置会话 Flask 自带会话管理功能,使用客户端 Cookie 存储会话数据.默认 ...

  10. itestwork(爱测试)开源一站式接口测试&敏捷测试工作站 9.0.0 GA 发布,重大升级

    (一)itest 简介 itest work (爱测试)  一站式工作站让测试变得简单.敏捷.itest work 包含极简的任务管理,测试管理,缺陷管理,测试环境管理,接口测试,接口Mock 6合1 ...