使用findVirtual

时间:2016-01-13 09:50:29

标签: java private-methods methodhandle

MethodHandle的Java文档说私有方法应该通过findSpecial.But调用,在下面的例子中,我可以通过findVirtual调用它。

有人可以解释一下我在这里缺少什么吗?

 import java.lang.invoke.MethodHandles;
import java.lang.invoke.*;

import java.lang.invoke.MethodType;

public class PrivateClassMethodLookupTest{
    public static void main(String[] args) throws Throwable{
     new PrivateClassMethodLookupTest().m();
     MethodHandle mh =   MethodHandles.lookup()
                .findVirtual(PrivateClassMethodLookupTest.class, "m", MethodType.methodType(void.class));
      mh.invoke(new PrivateClassMethodLookupTest());
    }

    private void m() { System.out.println("in m");}
}

1 个答案:

答案 0 :(得分:1)

您可以调用它,因为您可以访问运行main的同一个类中的私有方法 尝试运行此代码:

package com.company;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

public class PrivateClassMethodLookupTest {
    public static void main(String[] args) throws Throwable {
        new PrivateClassMethodLookupTest.Inner().m();
        MethodHandle mh = MethodHandles.lookup()
                .findVirtual(PrivateClassMethodLookupTest.Inner.class, "m", MethodType.methodType(void.class));
        mh.invoke(new PrivateClassMethodLookupTest.Inner());
    }

    static class Inner {
        private void m() {
            System.out.println("in m");
        }
    }
}

要调用私有方法,您应该使用Reflection API并更改方法访问类型:

package com.company;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;

public class PrivateClassMethodLookupTest {
    public static void main(String[] args) throws Throwable {
        new PrivateClassMethodLookupTest.Inner().m();
        Method declaredMethod = PrivateClassMethodLookupTest.Inner.class.getDeclaredMethod("m");
        declaredMethod.setAccessible(true);
        MethodHandle mh = MethodHandles.lookup().unreflect(declaredMethod);
        mh.invoke(new PrivateClassMethodLookupTest.Inner());
    }

    static class Inner {
        private void m() {
            System.out.println("in m");
        }
    }
}