原始内容如下:
http://www.java2000.net/viewthread.jsp?tid=6982
http://topic.youkuaiyun.com/u/20080707/10/a718ad57-a28d-4492-b1e9-f3048671260a.html
我们先看测试代码:
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class T {
public static synchronized void main(String[] a) throws Exception {
T t = new T();
Method m = t.getClass().getMethod("hasNext");
System.out.print(m.invoke(t));
List<T> list = new ArrayList<T>();
list.add(t);
Iterator it = list.iterator();
m = it.getClass().getMethod("hasNext");
System.out.print(m.invoke(it));
}
public boolean hasNext() {
return true;
}
}
运行结果为
trueException in thread "main" java.lang.IllegalAccessException: Class T can not access a member of class java.util.AbstractList$Itr with modifiers "public"
第一个true我们就不分析了,关键是第二个为何为异常??我们来看几个楼层的回复
Java2000_net:
T的getClass返回T,他的hasNext是一个public 方法,所以可以正常调用,输出true;
而 Iterator的 getClass 返回的是一个 java.util.AbstractList$Itr
我们可以输出看看
System.out.println(it.getClass());
那个Itr是一个inner Class, 其 hasNext 不是一个public方法,所以无法调用。
关键就是Iterator是一个接口而已。
Any_Yan:
呵呵,很有意思的一个问题!
ArrayList继承自AbstractList,其iterator()方法返回内部类Itr的一个实例,而AbstractList的内部类Itr签名是private 关键问题在最后一行"System.out.print(m.invoke(it));"上
Method的invoke方法参数是一个对象,内部到底决定是谁去调用这个Method呢?这里显然最后JVM决定用T来调用这个"hasNext"的Method对象,T肯定没有访问它的权利,至于底层原理,我会整明白再来回答,呵呵,上班暂时没空
import java.lang.reflect.Method;
public class T {
public static void main(String[] args)throws Exception{
T t = new T();
Sam sam = t.getIt();
Method m = sam.getClass().getMethod("f");
System.out.println(sam.getClass());
m.invoke(sam);
}
private class It implements Sam{
public void f(){
System.out.println("F method");
}
}
public Sam getIt(){
return new It();
}
}
public interface Sam{
public void f();
}
无语了,自己也模仿这个例子写了个程序,却无法重新楼主程序里出现的问题,一下子推理也不知道从哪里开始了。楼主那个程序中的异常是从Method类的invoke方法中有下面这行抛出来的:
其中caller是sun.reflect.Reflection.getCallerClass(1)返回的,由于不提供源码,所以无法深入跟踪
而clazz是Method对象的getDeclaringClass()方法返回的,这里就是AbstractList$Itr没有问题
obj是传入的iterator()方法返回的Iterator实现类对象也没有问题
modifiers是1,也就代表是Public方法,并不是7楼老紫竹说的,hasNext确实是一个Public方法
那么唯一可能出问题的就是第一个参数getCallerClass()返回的估计是Class T,而不是Class AbstractList$Itr类对象
Java2000_net
原因我找到了,是package的问题,请看如下代码: 下面是3个模仿的类,用于测试,请注意其package为 a
package a;
public interface MyCollection {
public MyIterator myIterator();
}
package a;
public interface MyIterator {
public void myHasNext();
}
package a;
public class MyArrayList implements MyCollection {
private class It implements MyIterator {
public void myHasNext() {
System.out.println("myHasNext method");
}
}
public MyIterator myIterator() {
return new It();
}
}
下面是我的测试类
package b;
import java.lang.reflect.Method;
import a.MyArrayList;
import a.MyCollection;
import a.MyIterator;
public class TestInvoke {
public static void main(String[] args) throws Exception {
MyCollection t = new MyArrayList();
MyIterator sam = t.myIterator();
Method m = sam.getClass().getMethod("myHasNext");
m.invoke(sam);
}
}
请注意其package为b 运行结果为
Exception in thread "main" java.lang.IllegalAccessException: Class b.TestInvoke can not access a member of class a.MyArrayList$It with modifiers "public"
at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at b.TestInvoke.main(TestInvoke.java:12)
如果你把测试类的放在和前面的3个类相同的package a 里面,则不会抱异常。
结论:
同包的可以调用。 不同包的比可以调用private的东西,虽然接口是public的
<script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>