• Java利用MethodHandle实现反射时调用super的method


    一:实现

    1.Base类的实现

    package me.silentdoer.reflecsuper;
    
    /**
     * @author silentdoer
     * @version 1.0
     * @description the description
     * @date 4/29/18 10:19 AM
     */
    public class Base {
    
        public String show(long num){
            System.out.println("Base" + num);
            return "BaseResult";
        }
    }

    2.Test类的实现

    package me.silentdoer.reflecsuper;
    
    /**
     * @author silentdoer
     * @version 1.0
     * @description the description
     * @date 4/29/18 10:20 AM
     */
    public class Test extends Base {
        @Override
        public String show(long num){
            System.out.println("Test" + num);
            return "TestResult";
        }
    }

    3.main方法所在类的实现

    package me.silentdoer.reflecsuper;
    
    import java.lang.invoke.MethodHandle;
    import java.lang.invoke.MethodHandles;
    import java.lang.invoke.MethodType;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    
    /**
     * @author silentdoer
     * @version 1.0
     * @description the description
     * @date 4/29/18 10:18 AM
     */
    public class Entrance {
        public static void main(String[] args) throws Throwable {
            MethodHandle h1, h2;
            MethodHandles.Lookup lookup = MethodHandles.lookup();
    
            Field allowedModes = MethodHandles.Lookup.class.getDeclaredField("allowedModes");
            allowedModes.setAccessible(true);
            allowedModes.set(lookup, -1);  // 关键,没有这三步的操作findSpecial方法内部this.checkSpecialCaller(specialCaller);会抛异常
    
            // TODO 这里第一个参数表示最终调用的是哪个层级类的某方法,第二个参数则是方法名,第三个参数是返回值类型加参数类型,第四个参数是要调用方法的对象的类型
            // TODO findSpecial是准确的要求调用第一个参数类的show方法,尽管调用的对象类是Test,注意最后一个参数的类型即Test必须是extends第一个参数(也可一样)
            h1 = lookup.findSpecial(Base.class, "show", MethodType.methodType(String.class, long.class), Test.class);
            h2 = lookup.findSpecial(Test.class, "show", MethodType.methodType(String.class, long.class), Test.class);
    
            // 用的是同一个对象,但是调用的方法却是不同层级类的show方法
            Test foo = new Test();
            System.out.println(h1.invoke(foo, 99L));
            System.out.println(h2.invoke(foo, 99L));
            /* 输出
            Base99
            BaseResult
            Test99
            TestResult
             */
        }
    }
  • 相关阅读:
    socket详解(二)----实例和多线程,线程池使用
    OpenJDK和JDK区别
    单词(11)
    程序员到项目经理:从内而外的提升(比较全面的介绍)
    如何成为一名自然语言处理工程师
    权限设计文章汇总
    ECharts+百度地图,默认选中 卫星地图
    Echarts3.0 引入百度地图(转载)
    echarts地图 鼠标滚动控制缩放大小比例(转载)
    echarts散点图 不显示问题 或宽度为0问题
  • 原文地址:https://www.cnblogs.com/silentdoer/p/8972429.html
Copyright © 2020-2023  润新知