专栏首页纯洁的微笑装逼利器,看完这篇,让只懂反射的同学仰视你

装逼利器,看完这篇,让只懂反射的同学仰视你

大家好,我是指北君。

昨天我朋友小 B ,在公司写 if else 被鄙视了,咱今天就来学一个装 x 利器。

反射(Reflect)作为Java最重要的一种机制,相信大家一定都很熟悉了,今天指北君要介绍另一种和反射机制类似的方法调用机制——MethodHandle。

MethodHandle是Java7引入的一种机制,主要是为了JVM支持动态语言。

一个MethodHandle调用示例

首先,让指北君给大家演示一下最基本的MethodHandle使用。

第一步:创建查找对象:Lookup

  // 获取Look用于查找方法句柄
  MethodHandles.Lookup lookup = MethodHandles.lookup();

第二步:创建方法类型:MethodType

构造方法的返回值类型,参数类型

  // 方法类型,描述返回值和参数,第一个参数为返回值类型,void则为void.class。第二个参数开始为被调用方法的参数类型
  MethodType mt = MethodType.methodType(boolean.class, String.class, int.class);

第三步:查找方法句柄

Lookup的findVirtual查找成员方法

  //查找方法句柄,参数1:调用类,参数2:方法名,参数3:方法类型
  MethodHandle handle = lookup.findVirtual(String.class, "startsWith", mt);

第四步:方法调用

通过MehodHandle的invoke方法执行,并返回结果

  //方法调用,参数1:实例,参数2..n:方法参数
  Boolean value = (Boolean)handle.invoke("the i am in the room", "the", 0);

以上就是一个简单的调用示例。

核心代码解读

上面我们展示了一个最进本MethodHandle方式的方法调用,下面我们将对其中用到的主要类进行介绍。这些主要的类包含MethodType,MethodHandle,MethodHandles及Lookup。

MethodType

首先,我们来看看Methodtype,MethodType是用来封装方法输入输出类型的,包含方法的返回和方法的参数。MethodType构造方法为私有,只能通过MethodType提供的静态工具方法来获取实例

    /**
     * Constructor that performs no copying or validation.
     * Should only be called from the factory method makeImpl
     */
    private MethodType(Class<?> rtype, Class<?>[] ptypes) {
        this.rtype = rtype;
        this.ptypes = ptypes;
    }

MethodType中常用的工具方法有:

  • 大于一个参数
    public static MethodType methodType(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) {
        Class<?>[] ptypes1 = new Class<?>[1+ptypes.length];
        ptypes1[0] = ptype0;
        System.arraycopy(ptypes, 0, ptypes1, 1, ptypes.length);
        return makeImpl(rtype, ptypes1, true);
    }
  • 无参数
    public static MethodType methodType(Class<?> rtype) {
        return makeImpl(rtype, NO_PTYPES, true);
    }

工具方法都通过makeImple方法来封装MethodType实例,指北君带领大家来看看makeImple中做了哪些事情:

  1. 参数检查
    • 返回值的类型不能为null,如果无返回使用void.class
    • 参数类型不能为null,且不能为void.class
  2. 使用缓存表缓存MethodType实例,优化处理
  3. 如果非信任模式(trusted==false),则克隆参数数组

这里需要注意MethodType重写了hashCode方法,从逻辑看参数数组克隆不影响同类型的缓存机制。

static
    MethodType makeImpl(Class<?> rtype, Class<?>[] ptypes, boolean trusted) {
        if (ptypes.length == 0) {
            ptypes = NO_PTYPES; trusted = true;
        }
        MethodType primordialMT = new MethodType(rtype, ptypes);
        MethodType mt = internTable.get(primordialMT);
        if (mt != null)
            return mt;

        // promote the object to the Real Thing, and reprobe
        MethodType.checkRtype(rtype);
        if (trusted) {
            MethodType.checkPtypes(ptypes);
            mt = primordialMT;
        } else {
            // Make defensive copy then validate
            ptypes = Arrays.copyOf(ptypes, ptypes.length);
            MethodType.checkPtypes(ptypes);
            mt = new MethodType(rtype, ptypes);
        }
        mt.form = MethodTypeForm.findForm(mt);
        return internTable.add(mt);
    }

除了静态工具方法外,MethodType还有几个实例方法,主要为差异性较小的MethodType提供快速获取实例的方法。包含:

  • changeParameterType
  • insertParameterTypes
  • appendParameterTypes
  • dropParameterTypes

MethodHandle

MethodHandle为抽象类,但是里面提供了大量的原生方法,提供底层访问,也是方法调用的核心逻辑。这部分涉及MethodHandle的机制实现,对于使用功能来说指北君就不在此展开了。

    @HotSpotIntrinsicCandidate
    public final native @PolymorphicSignature Object invokeExact(Object... args) throws Throwable;

    @HotSpotIntrinsicCandidate
    public final native @PolymorphicSignature Object invoke(Object... args) throws Throwable;

调用方法

MethodHandles, Lookup

MethodHandles不是MethodHandle的实现,他提供工具用于帮助获取MethodHandle,我们主要使用到lookup(),publicLookup()

@CallerSensitive注解,可以使Reflection.getCallerClass()获取到调用lookup()方法的类

    @CallerSensitive
    @ForceInline // to ensure Reflection.getCallerClass optimization
    public static Lookup lookup() {
        return new Lookup(Reflection.getCallerClass());
    }
    public static Lookup publicLookup() {
        return Lookup.PUBLIC_LOOKUP;
    }

Lookup构造方法主要传入两个参数:

  1. lookupClass搜寻的类,
  2. allowedModes:许可模式。

最后,通过Lookup的findXXX获取到MethodHandle,详细说明见下表:

查找方法

小结

关于MethodHandle的基本使用就基本讲完,这里指北君附上一张类图便大家理解:

最后感谢各位小伙伴的点赞、收藏和评论,我们下期更精彩。

本文分享自微信公众号 - 纯洁的微笑(keeppuresmile)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-06-10

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 1024程序员节,向改变世界的程序员致敬

    正值1024程序员节日来临之际,今天心血来潮,想写篇文章来为我们这些猿猿致敬,也算了却一个心愿,让我们这些猿猿们以自己从事的职业为豪为荣。

    Java高级架构
  • 这五点助你成为精英

    前一段时间一直在听吴军老师的《谷歌方法论》,可以说很新奇,给我打开了很大的一扇门,让我了解到很多不同领域的文化、知识,以及见识。

    宇相
  • 罗浩:创业降级论

    几乎一年没有写博客了,说没时间那是借口,唯一的原因是,年纪越大越发觉自己肤浅。有些想法还没提笔,就发现很幼稚,就不敢发出来贻笑大方了。这次先给大家说个小故事: ...

    春哥大魔王
  • 一位数学专业女生大学毕业前的感慨:不好意思,是我天真了

    问自己永远有多远!!!! 已知X是非平方数,证明X开根号是无理数 TM这还需要证明 学完定与不定积分后

    华章科技
  • 春天,是腾讯码农丰收的季节

    春天来了,万物复苏,又到了………… 学霸码农们丰收的季节! ? 这次丰收的“农场”是即将在美国举办的IEEE CVPR 2019(Computer Visio...

    腾讯大讲堂
  • 【强化学习炼金术】李飞飞高徒带你一文读懂RL来龙去脉

    来源: 心有麟熙 作者: Jim 范麟熙 编辑:常佩琦 【新智元导读】斯坦福大学博士生、师从李飞飞教授的Jim Fan(范麟熙)带你一文读懂强化学习的来龙去脉。...

    新智元
  • 开发者\b都喜欢用mac?必须哒

    很可惜,我的第一台mac不是自己买的,是公司里面的一个ios开发用剩下的。不过机器不算是很老,相反性能还很好,是2015款的mac book pro有16g内存...

    Jean
  • 【涨姿势】绝不装逼的大数据科普(二)

    言归正传,今天带来浅显易懂的大数据科普(二),会围绕一些大数据的关键概念重点普及一下,如果您已经很懂了也不要跑,本文可作为您的最佳厕所读物。 数据(data)这...

    小莹莹
  • 不会装逼的程序员,还怎么改变世界?|附装逼指南

    可能我们的着装遭人吐槽,可能我们的玩笑经常别人听不出笑点,可能我们心照不宣的执着外人觉得莫名其妙,可能我们的举止身边的人觉得实在无趣,也可能我们在如今互联网火热...

    BestSDK
  • 21届毕业学长的辛酸求职面试之旅:可能是最走心的校招经验

    学历好的话,请亮剑 -- 现实告诉我们学历就是牌面,如果学校是985、211、海外高校的大佬们,请别隐藏自己了。小弟只有瞻仰....

    宇宙之一粟
  • 1024程序员节,向改变世界的程序员致敬!

    写在前面 正值1024程序员节日来临之际,今天心血来潮,想写篇文章来为我们这些猿猿致敬,也算了却一个心愿,让我们这些猿猿们以自己从事的职业为豪为荣。 可能我们的...

    Java高级架构
  • python绘图 | 气象雷达入门级讲解&多种雷达图像可视化方法

    气象雷达是专门用于大气探测的雷达。它是一种主动式微波大气遥感设备。 气象雷达是气象观测的重要设备,特别是在突发性、灾害性的监测、预报和警报中具有极为重要的作用,...

    郭好奇同学
  • 【工作经验分享】:在滴滴和头条干了 2 年开发,这些太真实…

    先简单交代一下背景吧,某不知名985的本硕,17年毕业加入滴滴,今年下半年跳槽到了头条,一直从事后端研发相关的工作。

    Android技术干货分享
  • 刷新ImageNet纪录,GAN不只会造假!DeepMind用它做图像分类,秒杀职业分类AI

    DeepMind的两位大佬,改造了“史上最强”的BigGAN,让新的算法去做图像分类,刷新了ImageNet无监督表征学习的纪录。

    量子位
  • Parrot Anafi AI无人机介绍.上

    法国无人机厂商Parrot将在下半年发布全新无人机“Anafi AI",快来看看吧!

    云深无际
  • 十个生成模型(GANs)的最佳案例和原理 | 代码+论文

    王小新 编译 原文作者:Sumeet Agrawal 量子位 出品 | 公众号 QbitAI 生成对抗网络(GANs)是一种能“教会”计算机胜任人类工作的有趣方...

    量子位
  • 我的技术成长之路

    上面就是我目前的状态了,如果大家觉得能力比我弱那么一丢丢的话,那么还是可以继续把文章看下去的,应该会对你有所帮助。

    何时夕
  • 一直不明白,程序员为何老加班!

    今天说好的需求这样做,亲自找到他跟他确认,然后过几天,他又反悔了。说自己从没说过,要另外的实现方式。

    AI科技大本营
  • RoboMaster S1 高清大图+改装建议

    拿到东西的第一印象就是很沉,硕大的一个纸箱子放着拆分开的机器,邮寄时其底座与云台相分离,之后急急忙忙的安装好以后打开App,连接,许久无果。后来想着是不是下面还...

    云深无际

扫码关注云+社区

领取腾讯云代金券