Java 业务开发常见错误 100 例
朱晔
贝壳金服资深架构师
52944 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 48 讲
代码篇 (23讲)
Java 业务开发常见错误 100 例
15
15
1.0x
00:00/00:00
登录|注册

18 | 当反射、注解和泛型遇到OOP时,会有哪些坑?

Spring的工具类AnnotatedElementUtils
@Inherited注解
子类无法继承父类注解
注解的作用
修复方法
问题出现
泛型概念
解决方法
方法调用确定方式
误区:反射调用方法根据入参确定方法重载
反射功能
其他Java高级特性相关的坑
Spring的常用注解是否支持继承
synthetic方法生成情况
注解可以继承吗?
泛型经过类型擦除多出桥接方法的坑
反射调用方法不是以传参决定重载
思考与讨论
反射、注解和泛型
Java高级特性

该思维导图由 AI 生成,仅供参考

你好,我是朱晔。今天,我们聊聊 Java 高级特性的话题,看看反射、注解和泛型遇到重载和继承时可能会产生的坑。
你可能说,业务项目中几乎都是增删改查,用到反射、注解和泛型这些高级特性的机会少之又少,没啥好学的。但我要说的是,只有学好、用好这些高级特性,才能开发出更简洁易读的代码,而且几乎所有的框架都使用了这三大高级特性。比如,要减少重复代码,就得用到反射和注解(详见第 21 讲)。
如果你从来没用过反射、注解和泛型,可以先通过官网有一个大概了解:
接下来,我们就通过几个案例,看看这三大特性结合 OOP 使用时会有哪些坑吧。

反射调用方法不是以传参决定重载

反射的功能包括,在运行时动态获取类和类成员定义,以及动态读取属性调用方法。也就是说,针对类动态调用方法,不管类中字段和方法怎么变动,我们都可以用相同的规则来读取信息和执行方法。因此,几乎所有的 ORM(对象关系映射)、对象映射、MVC 框架都使用了反射。
反射的起点是 Class 类,Class 类提供了各种方法帮我们查询它的信息。你可以通过这个文档,了解每一个方法的作用。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文通过实例分析了在使用Java高级特性时需要注意的一些细节和陷阱,帮助读者更好地理解和运用这些特性。文章首先介绍了反射调用方法时需要注意方法签名的确定,以及反射、泛型擦除和继承结合时可能产生的问题。其次,文章讨论了子类方法重写父类方法失败的原因,包括子类没有指定泛型参数和子类的方法没有增加@Override注解。文章还指出了使用反射查询类方法清单时需要注意getMethods和getDeclaredMethods的区别,以及反射进行方法调用要注意过滤桥接方法。通过这些案例,读者可以了解到在使用Java高级特性时需要注意的一些细节和陷阱,帮助他们更好地理解和运用这些特性。同时,文章还介绍了注解的继承问题,以及Spring提供的工具类AnnotatedElementUtils来处理注解的继承问题。总之,本文深入浅出地解析了Java高级特性中的反射、注解和泛型,为读者提供了宝贵的技术指导和实践经验。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Java 业务开发常见错误 100 例》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(15)

  • 最新
  • 精选
  • 👽
    置顶
    这一讲满满的知识盲区。。。 思考题2: 不可继承,我简单测试了一下。 另外,使用经验上也能说明不可继承。 因为,你想,我们通常的controller类,都会使用controller注解,如果可以被继承的话,Spring就不会只让我们使用Controller注解了,会提供另一种方式注入Controller组件,就是继承BaseController类。

    作者回复: 是 https://github.com/spring-projects/spring-framework/issues/8859: 『The problem with inheritance is that those annotations are really supposed to apply to specific concrete classes. Standard annotations with similar meaning, e.g. in JPA or EJB 3, are designed analogously, not being marked as inherited either.』

    2020-04-24
    7
  • Darren
    1、内部类会用到,类在JVM是最顶级的,即使是内部类,编译以后,都会存在外部类$1这样的class文件;外部类是能完全访问内部的方法的,即使是private,但编译后编程2个文件了,怎么访问的,就是通过synthetic标识位实现的。 在额外分享两篇R大关于逃逸分析的文章,里面涉及到了synthetic。 http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/2016-September/024535.html http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/2016-September/024535.html 2、不会被继承,因为我的理解是继承后,RequestMapping对应的在父子类都能找到,处理起来肯定会很麻烦,在加上这几个注解默认都是单例的,所以是不能继承的。

    作者回复: 感谢分享

    2020-04-24
    21
  • 终结者999号
    老师您好,我听我们架构师说生产上最好不要使用反射会对性能有影响,有依据吗?

    作者回复: 一般情况下这些不会成为性能瓶颈,除非并发特别大,一次处理又涉及几千几万次反射,各种框架内部也大量使用反射,不必这么绝对

    2020-04-23
    3
    20
  • 旭东(Frank)
    java 的泛型真不怎么样,实现没有c#实现的好

    作者回复: 是

    2020-04-24
    6
  • kyl
    老师,后续能不能出一个结合项目利用一些高级特性、jdk新特性、设计模式实现高质量编码的课程,感觉工作中写的代码质量不够高又不知道如何快速提高。

    作者回复: 设计篇第一篇文章会有一点有关这方面的介绍

    2020-04-24
    6
  • Jackson
    老师,我使用了getDeclaredMethods,但是父类还是输出了两次,我用stream流的debug发现,子类其实还是有两个方法一个是String一个是Object,我也看了getDeclaredMethods这个方法其实是不包含父类的。 including public, protected, default (package) * access, and private methods, but excluding inherited methods

    作者回复: 这个问题的原因我文中有解释

    2020-04-24
    3
    3
  • 汝林外史
    findAllMergedAnnotations(AnnotatedElement element, Class<A> annotationType) getAllMergedAnnotations(AnnotatedElement element, Class<A> annotationType) 老师,这两个方法除了名字不一样,我看入参,出参,描述都是一样的,那区别在哪呢?

    作者回复: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/annotation/AnnotatedElementUtils.html Find vs. Get Semantics一节 Get对应 SearchStrategy.INHERITED_ANNOTATIONS: /** * Find all directly declared annotations as well as any * {@link Inherited @Inherited} superclass annotations. This strategy * is only really useful when used with {@link Class} types since the * {@link Inherited @Inherited} annotation is ignored for all other * {@linkplain AnnotatedElement annotated elements}. This strategy does * not search implemented interfaces. */ Find 对应 SearchStrategy.TYPE_HIERARCHY: /** * Perform a full search of the entire type hierarchy, including * superclasses and implemented interfaces. Superclass annotations do * not need to be meta-annotated with {@link Inherited @Inherited}. */

    2020-04-27
    1
  • Blackwaltz
    老师,子类foo方法本身并没有通过继承获得MyAnnotation注解,而使用了AnnotatedElementUtils.findMergedAnnotation(child.getClass().getMethod("foo"), MyAnnotation.class)之后,只是拿到了父类MyAnnotation注解为自己所用,而本身依然没有在程序运行的任何时段获得MyAnnotation注解,能这样理解吗?

    作者回复: 注解只是一个元数据,子类怎么使用父类上的元数据,还是基于我们自己的实现

    2020-04-23
    1
  • 远山
    写的很棒,很喜欢

    作者回复: :)

    2023-05-16归属地:北京
  • Rhinos HiL.
    第一个问题,采用sonar计算单元测试代码覆盖率的时候,用会java探针技术插入。

    作者回复: 是,但这个动态字节码注入和synthetic还是有区别的。

    2020-07-04
收起评论
显示
设置
留言
15
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部