Java子类是否能继承父类上的注解
子类可以继承到父类上的注解吗?
在编写自定义注解时,可以通过指定@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方法。
注解的合并使用
合并注解的含义
- 注解只在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,实现记录操作日志
接口使用自定义注解,实现控制请求限流和防止表单重复提交
实体类使用自定义注解,实现校验字段唯一性
实体类字段使用自定义注解,实现数据脱敏
Java子类是否能继承父类上的注解的更多相关文章
- 转:Java中子类是否可以继承父类的static变量和方法而呈现多态特性
原文地址:Java中子类是否可以继承父类的static变量和方法而呈现多态特性 静态方法 通常,在一个类中定义一个方法为static,那就是说,无需本类的对象即可调用此方法,关于static方法,声明 ...
- Java中子类是否可以继承父类的static变量和方法而呈现多态特性
静态方法 通常,在一个类中定义一个方法为static,那就是说,无需本类的对象即可调用此方法,关于static方法,声明为static的方法有以下几条限制: 它们仅能调用其他的static 方法. 它 ...
- @interface __ annotation 子类可以继承到父类上的注解吗--有结论了
博客分类: Java/J2se 作者:赵磊 博客:http://elf8848.iteye.com 不了解注解基础知识的请先看<JDK 5 Annotation\注解\注释\自定义注解> ...
- Java -- 子类使用super调用父类的方法A,A 调用了方法B,子类也override方法B,那么super.A()最终调用到了子类的B方法
public class SuperClass{ public void printA(){ System.out.print("SuperClass-printA"); prin ...
- java 子类不能继承父类的static方法
先来看一段代码 /** * Created by bjchengpeng on 2018/7/19. */ /**运行结果 * woof * woofaa * * woof * Basenjiaa * ...
- Java中子类能继承父类的私有属性吗?
前段时间去听老师讲课的时候,老师告诉我子类是可以继承父类所有的属性和方法的.当时我是极其疑惑的,因为之前学校考试时这个考点我记得很清楚:子类只能继承父类的非私有属性和方法.老师给我的解释是这样的--先 ...
- javascript中子类如何继承父类
参考阮一峰的文章:http://javascript.ruanyifeng.com/oop/inheritance.html#toc4 function Shape() { this.x = 0; t ...
- Net基础篇_学习笔记_第十二天_面向对象继承(父类和子类)
继承 我们可能会在一些类中,写一些重复的成员,我们可以将这些重复的成员,单独的封装到一个类中,作为这些类的父类.Student.Teacher.Driver 子类 派生类Person ...
- (转)Java:类与继承
原文地址: http://www.cnblogs.com/dolphin0520/p/3803432.html 对于面向对象的程序设计语言来说,类毫无疑问是其最重要的基础.抽象.封装.继承.多态这四大 ...
- Java:类与继承
Java:类与继承 对于面向对象的程序设计语言来说,类毫无疑问是其最重要的基础.抽象.封装.继承.多态这四大特性都离不开类,只有存在类,才能体现面向对象编程的特点,今天我们就来了解一些类与继承的相关知 ...
随机推荐
- .NET有哪些好用的定时任务调度框架
前言 定时任务调度的相关业务在日常工作开发中是一个十分常见的需求,经常有小伙伴们在技术群提问:有什么好用的定时任务调度框架推荐的?今天大姚给大家分享5个.NET开源.简单.易用.免费的任务调度框架,帮 ...
- cesium教程3-加载3dtile模型,并调整位置
直接上示例代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...
- Nifi:Nifi中的Controller Service
Service简介 首先Nifi中的Controller Service 和我们MVC概念中的Controller Service不是一个概念,Nifi中的Controller Service更像是和 ...
- P3667 Bovine Genomics Hash+二分题解
砂金听说了你在学字符串,于是在CLOI里出了道题给你 P3667 Bovine Genomics 题链:洛谷 hzoi提高 \(hash\)基础题. 思路是二分答案,\(check\)中比较每一个区间 ...
- Python基础篇(安装)
Python简介 Python是Guido van Rossum发布于1991年的一种计算机程序设计语言.是一种动态的.面向对象的脚本语言,是一种解释型的,弱类型的高级计算机语言.需要注意的是pyth ...
- linux文件权限管理:文件权限类型,文件权限影响,设定文件权限,取消文件权限
目录 一.关于文件权限 二.查看文件权限 三.linux下常见文件类型 四.linux下常见的文件权限 五.权限对文件和目录的影响 六.文件的用户分类 七.更改文件的属主和属组 八.一个文件取消所有权 ...
- 二进制安装Kubernetes(k8s)v1.30.1
二进制安装Kubernetes(k8s)v1.30.1 https://github.com/cby-chen/Kubernetes 开源不易,帮忙点个star,谢谢了 介绍 kubernetes(k ...
- 初步搭建一个自己的对象存储服务---Minio
docker安装 1.拉取镜像 docker pull minio/minio 2.启动镜像 docker run -p 9000:9000 -p 9001:9001 --name minio -d ...
- Anaconda安装Python的seaborn库
本文介绍在Anaconda的环境中,安装Python语言中,常用的一个绘图库seaborn模块的方法. seaborn模块是基于Matplotlib的数据可视化库,它提供了一种更简单.更漂亮的 ...
- 震惊!docker镜像还有这些知识,你都知道吗?----镜像(一)
镜像操作命令表格 docker image 子命令 docker子命令 功能 docker image build docker build 从Dockerfile开始构建镜像 docker imag ...