java反射使用setAccessible(true)调用private方法问题

如题,定义了一个Person类有一个private方法

public Person {
    private void test();//private方法
}

使用反射来调用
先说有问题的方法

Constructor con= Person.class.getConstructor();//构造方法
Object object = con.newInstance();//生成对象
//有问题
Person.class.getDeclareMethod("test").setAccessible(true);
Person.class.getDeclareMethod("test").invoke(object);//报错不能访问
/*Person.class.getDeclareMethod("test").isAccessible()还是等于false*/

而使用下面的写法却可以

Method = Person.class.getDeclareMethod("test");
method.setAccessible(true);
method.invoke(object);//不报错,正常执行
/*method.isAccessible()是true
而Person.class.getDeclareMethod("test").isAccessible()还是等于false
*/

这是Person.class.getDeclareMethod("test")方法的问题吗,这个问题在反射调用构造函数时也会出现,他们都有一个@CallerSensitive注解,是这个原因吗?望解答。

慕田峪7331174
浏览 1002回答 3
3回答

qq_遁去的一_1

每次获取方法得到不是同一个Method对象 setAccessable仅作用于得到的方法对象,也不是全局的 所以第一种写法会报错 另外,setAccessable的属性并没有被包含在Method的equals 和hashCode中

拉莫斯之舞

@CallerSensitive public Method getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); } return method; } private static Method searchMethods(Method[] methods, String name, Class<?>[] parameterTypes) { Method res = null; String internedName = name.intern(); for (int i = 0; i < methods.length; i++) { Method m = methods[i]; if (m.getName() == internedName && arrayContentsEq(parameterTypes, m.getParameterTypes()) && (res == null || res.getReturnType().isAssignableFrom(m.getReturnType()))) res = m; } return (res == null ? res : getReflectionFactory().copyMethod(res)); } ... 到最后,其实是: /** * Package-private routine (exposed to java.lang.Class via * ReflectAccess) which returns a copy of this Method. The copy's * "root" field points to this Method. */ Method copy() { // This routine enables sharing of MethodAccessor objects // among Method objects which refer to the same underlying // method in the VM. (All of this contortion is only necessary // because of the "accessibility" bit in AccessibleObject, // which implicitly requires that new java.lang.reflect // objects be fabricated for each reflective call on Class // objects.) if (this.root != null) throw new IllegalArgumentException("Can not copy a non-root Method"); // 注意这里,意味着每次调用都会new一个Method对象 Method res = new Method(clazz, name, parameterTypes, returnType, exceptionTypes, modifiers, slot, signature, annotations, parameterAnnotations, annotationDefault); res.root = this; // Might as well eagerly propagate this if already present res.methodAccessor = methodAccessor; return res; }

狐的传说

以前我还真没有注意到这个问题,我帮你验证了一下. Constructor con = People.class.getConstructor();//构造方法 Object object = con.newInstance();//生成对象 Method test1 = People.class.getDeclaredMethod("test"); test1.setAccessible(true); Method test2 = People.class.getDeclaredMethod("test"); System.out.println(test1.hashCode());//一样的hashcode System.out.println(test2.hashCode());//一样的hashcode test1.invoke(object);//正常 我能想到的解释是: test1 和 test2 的引用不是一个,但是equals和hashcode又是一样的,让我也迷惑了.但解释应该还是我想到但那样,他们但引用是不相同的
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java