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:类与继承 对于面向对象的程序设计语言来说,类毫无疑问是其最重要的基础.抽象.封装.继承.多态这四大特性都离不开类,只有存在类,才能体现面向对象编程的特点,今天我们就来了解一些类与继承的相关知 ...
随机推荐
- linux开发vue项目,不能热更新?
只需要运行下面的命令即可: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo ...
- iframe 高度设置为0时还有占位_iframe占位
iframe是一个内联元素,默认是跟baseline对齐的,iframe后边有个看不见.摸不着的行内空白节点,空白节点占据着高度,iframe与空白节点的基线对齐,导致了div被撑开,从而出现滚动条, ...
- uniapp底层跨端原理
uniapp底层跨端原理 - 代码编写:开发者使用Vue.js框架编写uniapp的代码,包括页面结构.样式和逻辑等. - 编译过程:在编译过程中,uniapp会将Vue.js的代码转换为各个平台所需 ...
- AIRIOT答疑第7期|如何快速提升物联网项目交付速度?
平台+模板,套上就能用!贼拉快! AIRIOT提供物联网低代码平台+多套行业案例模板,针对于有明确项目的服务商,用平台已经配置好的节点数.功能模块.流程,直接上手干项目! AIRIOT解答: 多套物联 ...
- MySQL所有的主从同步架构搭建方式
目录 一.前言 二.关于MySQL主从同步 三.部署规划 3.1 服务器规划 3.2 数据库目录规划 四.准备工具 五.四台机器上使用通用二进制包安装MySQL(以node7为例) 5.1 上传MyS ...
- 分享5款.NET开源免费的Redis客户端组件库
前言 今天大姚给大家分享5款.NET开源.免费的Redis客户端组件库,希望可以帮助到有需要的同学. StackExchange.Redis StackExchange.Redis是一个基于.NET的 ...
- Postman POST多个文件
软件做的比较好用,
- react类组件
使用ES6语法的class创建的组件(有状态组件) 类名称必须要大写字母开头 类组件要继承React.Component父类,从而可以使用父类中提供的方法或者属性 类组件必须提供 render 方法, ...
- v-once指令 v-if和v-show
v-once指令 只渲染元素和组件一次,之后元素和组件将失去响应式功能 v-if和v-show 根据表达式的布尔值(true/false)进行判断是否渲染该元素 注:v-if 有更高的切换开销,而 v ...
- vue devtools工具安装 Vue实现数据绑定的原理
通过chrome中的谷歌插件商店安装Vue Devtools工具,此工具帮助我们进行vue数据调试所用,一定要安装. https://chrome.google.com/webstore?utm_so ...