黑马程序员技术交流社区

标题: [已解决]获得关于迭代器的一个问题 [打印本页]

作者: 胡宝林    时间: 2012-6-4 08:42
标题: [已解决]获得关于迭代器的一个问题
本帖最后由 hy19985125 于 2012-6-4 10:59 编辑

import java.util.*;

import java.lang.reflect.*;
public class C {
    public static void main(String[] args) throws Exception {
        Set<String> s = new HashSet<String>();
        s.add("a");
        Iterator it = s.iterator();
        Method m = it.getClass().getMethod("hasNext");
        System.out.println(m.invoke(it));
    }
}
通过反射的方法获取迭代器的hasNext方法,然后在执行这个方法,就相当于it.hasNext();  

程序执行本该打印true,但是却报了异常,求高手解答!!!!
作者: 郭宁    时间: 2012-6-4 09:03
楼主要学着看错误信息:
Exception in thread "main" java.lang.IllegalAccessException: Class B can not access a member of class java.util.HashMap$HashIterator with modifiers "public final"
它说不能访问,那就应该想到m.setAccessible(true);
具体为何我也不清楚,就像用反射访问private 成员,也得m.setAccessible(true);
作者: 唐辉辉    时间: 2012-6-4 09:09
java.lang.IllegalAccessException
安全权限异常,一般来说,是由于java在反射时调用了private方法所导致的。
如果是这种情况的话,要把反射pirvate的方向设置成public,再调用.
作者: 胡宝林    时间: 2012-6-4 09:15
郭宁 发表于 2012-6-4 09:03
楼主要学着看错误信息:
Exception in thread "main" java.lang.IllegalAccessException: Class B can not  ...

不是权限的问题,我暴力了一下,m.setAccessible(true);之后还是报这个异常
作者: 郭宁    时间: 2012-6-4 09:17
hy19985125 发表于 2012-6-4 09:15
不是权限的问题,我暴力了一下,m.setAccessible(true);之后还是报这个异常

我这边可以的啊!
作者: 闾丘日月    时间: 2012-6-4 09:17
本帖最后由 闾丘日月 于 2012-6-4 11:14 编辑

占楼先,我来看看,好难啊,解决不了。把我的所得汇报一下吧
抛出异常的函数为 Reflection.ensureMemberAccess(caller, clazz, obj, modifiers);
抛异常的语句为             if (!verifyMemberAccess(currentClass, memberClass, target, modifiers)) {            
                                             throw new IllegalAccessException("Class " + currentClass.getName() +
                                             " can not access a member of class " +
                                             memberClass.getName() +
                                             " with modifiers \"" +
                                             Modifier.toString(modifiers) +
                                             "\"");
  它根据verifyMemberAccess函数的返回值是真还是假来判断能否抛异常,
  至于这个函数逻辑太过复杂,我看晕掉了,而且我不知道传的参数是哪些,怎么传进来的。

作者: 胡宝林    时间: 2012-6-4 09:17
郭宁 发表于 2012-6-4 09:03
楼主要学着看错误信息:
Exception in thread "main" java.lang.IllegalAccessException: Class B can not  ...

我查看了文档,hasNext这个方式public的,不是private的
作者: 胡宝林    时间: 2012-6-4 09:41
ttkl123654 发表于 2012-6-4 09:15

加上m.setAccessible(true); 确实可以打印出true,也不报异常了,但是hasNext也不是private私有的方法
如果他是私有的,那么it.hasNext(); 也不能执行的,私有的方法只能在本类中执行,既然不是私有的方法
又为何要设置访问权限m.setAccessible(true); 呢???
作者: 郭宁    时间: 2012-6-4 13:42
hy19985125 发表于 2012-6-4 09:17
我查看了文档,hasNext这个方式public的,不是private的

摘自JAVA解惑


hasNext方法当然是公共的,所以它在任何地方都是可以被访问的。那么为什么这个基于反射的方法调用是非法的呢?这里的问题并不在于该方法的访问级别(access level),而在于该方法所在的类型的访问级别。这个类型所扮演的角色和一个普通方法调用中的限定类型(qualifying type)是相同的.在这个程序中,该方法是从某个类中选择出来的,而这个类型是由从it.getClass方法返回的Class对象表示的。这是迭代器的动态类型(dynamic type),它恰好是私有的嵌套类(nested class) java.util.HashSet.Iterator。出现 IllegalAccessException 异常的原因就是这个类不是公共的,它来自另外一个包:访问位于其他包中的非公共类型的成员是不合法的。无论是一般的访问还是通过反射的访问,上述的禁律都是有效的。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2