Java类型描述符,与LambdaWrapper源码底层探究

阿超 阿超 | 146 | 2022-09-06

年轻人在科学的进程中要有冲刺力,当你老了,就会越来越胆小——杨振宁

java中,由于历史原因,出现在类文件结构中的二进制名称语法与我们常用的类名不同,通常使用(正斜杠)/替换了原本的包名间隔(句号).

例如Thread的类名叫java.lang.Thread,但是在class文件格式的描述符中使用的内部格式,对Thread类名称utf8的引用却是:java/lang/Thread

不信我们随便打开一个class文件

image-20220607130246228

可以看到类似的描述符

那如何获取类的描述符呢?它的规则又是如何呢?

首先,基本类型描述符,都是以ASCII字符表示,例如L 正斜杠类名;表示对象类型,[表示数组类型

我们可以在sun.invoke.util.Wrapper下看到对应枚举常量

image-20220607124946733

例如:

  • int的描述符为I

  • Integer的描述符为Ljava/lang/Integer;

  • void的描述符为V

  • java.lang.Void的描述符为Ljava/lang/Void;

  • Object的描述符为Ljava/lang/Object;

  • double d[][][]的描述符为[[[D

然后方法描述符的规则是:

(参数描述符们)返回值描述符

例如:

这样一个方法:

Object m(int i, double d, Thread t) {..}

它的描述符为

(IDLjava/lang/Thread;)Ljava/lang/Object;

而我们的java.io.PrintStream#println(java.lang.Object)也就是我们常用的System.io.println(obj)

     public void println(Object x) {
        String s = String.valueOf(x);
        synchronized (this) {
            print(s);
            newLine();
        }
    }

描述符为

(Ljava/lang/Object;)V

java.lang.Integer#compare——public static int compare(int x, int y) {..}的描述符为(II)I

现在很多人有疑问了,知道这个类型描述符的规则又如何,什么场景下用得到?

这就是LambdaWrapper能通过Lambda获取字段名的核心啦~

举个例子:

假设现在想通过

Serializable stringConsumer = (Serializable & Function<TestModel, String>) TestModel::getName;

这样的Lambda获取其方法名

可以使用反射调用其writeReplace方法

        Serializable stringConsumer = (Serializable & Function<TestModel, String>) TestModel::getName;
        Method writeReplace = stringConsumer.getClass().getDeclaredMethod("writeReplace");
        writeReplace.setAccessible(true);
        java.lang.invoke.SerializedLambda serializedLambda = (java.lang.invoke.SerializedLambda) writeReplace.invoke(stringConsumer);

获取到序列化后的Lambda,其中包含lambda的很多信息了

839dad997a324eae9957cdcb47986efd.png

这也是Mybatis-PlusLambdaWrapper底层实现原理,我也对其进行了在idea进行Debug时的evaluate窗口进行了一些小优化

见:https://gitee.com/baomidou/mybatis-plus/pulls/241

82df8a9cb63c4528af63444ad8ffdde1.png

参考jdk文献:

https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html

https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.2.1

文章标签: JavaMybatisPlus
推荐指数:

真诚点赞 诚不我欺~

Java类型描述符,与LambdaWrapper源码底层探究

点赞 收藏 评论

关于作者

阿超
阿超

​ 我的名字叫阿超 年龄21岁 家在四川省成都市 未婚 职业是软件开发 每天最晚也会在八点前回家 不抽烟 酒浅尝辄止 晚上十二点上床 保证睡足八个小时 睡前写一篇博客 再做二十分钟俯卧撑暖身 然后再睡觉 基本能熟睡到天亮 像婴儿一样不留下任何疲劳和压力 就这样迎来第二天的早晨 健康检查结果也显示我很正常 我想说明我是一个不论何时都追求内心平稳的人 不拘泥于胜负 不纠结于烦恼 不树立使我夜不能寐的敌人 这就是我在这社会的生活态度

等级 LV1

粉丝 3

获赞 7

经验 73