• 不使用反射如何调用某个实例对象的方法


    本文转载自不使用反射如何调用某个实例对象的方法

    导语

    如何调用一个对象的方法?我们可以通过实例化对象直接调用、使用反射机制、通过代理对象等,本文介绍一种新的方法MethodHandle,这种方法在开发中很少会用到,但使用起来感觉很顺手。

    什么是MethodHandle?

    MethodHandle是JDK1.7实现了JSR-292,新加入的java.lang.invoke包中的一个重要组成部分,这个包的主要是在单纯通过符号引用来确定调用的目标方法以外,提供一种析的动态确定目标方法的机制。

    示例

    package com.bk.exercise;
    
    import java.lang.invoke.MethodHandle;
    import java.lang.invoke.MethodHandles;
    import java.lang.invoke.MethodType;
    /**
     * @author BK
     * @description:
     * @date 2019-08-19 22:34
     */
    public class MethodHandlerTest {
        static class Person{
            public void sing(String songName){
                System.out.println("I'm sing " + songName);
            }
        }
        /**
         * 实现调用Person类的sing方法
         * @param args
         */
        public static void main(String[] args) throws Throwable {
            Person zhangsan = new Person();
            // void.class是方法返回的类型    String.class 是方法的入参类型
            MethodType mt = MethodType.methodType(void.class,String.class);
            MethodHandle handler = MethodHandles.lookup()
                    //找到zhangsan对象中签名和mt指定的签名是一致的sing方法
                    .findVirtual(zhangsan.getClass(), "sing", mt)
                    //非静态方法的第一个参数隐藏的this指针,这步相当设置第一个参数this指针
                    .bindTo(zhangsan);
            handler.invokeExact("Summer train ");
        }
    }
    

    运行结果如下显示

    I'm sing Summer train
    

    从示例可以看出来,使用MethodHandle并没有什么困难,可以实现方法的调用,可是很多人会问,反射不也可以做相同的事情么,我们经常会使用反射,而不会使用这种方法。

    MethodHandle与Reflection的区别

    如果站在Java语言的角度来看,他们确实是有很多相似之处,但是从他们其它角度来看,确有很大的区别

    1. 从本质上来讲,ReflectionMethodHandle机构都是在模拟方法调用,但Reflection是模拟的Java代码层面的方法调用,而MethodHandle是在模拟字节码层面的方法调用。
    2. Reflection中的Method是重量级的,MethodHandle对象是轻量级的,Reflection中包含了方法的签名、描述符以及方法属性表中各种属性、执行权限等,而MethodHandle仅仅包含与执行该方法相关的信息
    3. MethodHandle是字符码的方法指令调用模拟,理论上可以模拟出和JVM上一样的优化如方法内联,但是Reflection去调用方法则不可以
    4. Reflection API的设计目标是为Java语言服务的,而MethodHandle设计成可服务于所有Java虚拟机之上的语言

    写在最后

    MethodHandles.lookup中的findStatic()findVirtual()findSpecia()三个谅正是为了对应invokestaticinvokevirtual&invokeinterface、invokespecial这几条字节码指令的执行权限校验行为,本文中只讲到了findVirtual()方法,其它两个方法读者可以自行尝试一下。

    java.lang.invoke包中的内容可以看一看,别有一番有洞天。

  • 相关阅读:
    【转】java的string中,关于split空串总会返回单个元素的数组
    【转】Java实现将文件或者文件夹压缩成zip
    单例模式
    数据库隔离级别
    ckeditor+ckfinder
    extremecomponents
    在linux环境下重启oracle数据库,解决密码过期的问题
    20180918 begin
    hadoop免登录
    CentOS环境下通过YUM安装软件,搭建lnmp环境
  • 原文地址:https://www.cnblogs.com/yungyu16/p/13197979.html
Copyright © 2020-2023  润新知