请写出如下代码的运行结果(22)
- Java code
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:
[解决办法]
trueException in thread "main" java.lang.IllegalAccessException: Class T can not access a member of class java.util.AbstractList$Itr with modifiers "public"
System.out.print(m.invoke(it));//出错
[解决办法]
打印 iterator 的hasnext()的所调用的底层方法
[解决办法]
[解决办法]
你是来问问题的还是来面试的?????
[解决办法]
T的getClass返回T,他的hasNext是一个public 方法,所以可以正常调用,输出true;
而 Iterator的 getClass 返回的是一个 java.util.AbstractList$Itr
我们可以输出看看
System.out.println(it.getClass());
那个Itr是一个inner Class, 其 hasNext 不是一个public方法,所以无法调用。
关键就是Iterator是一个接口而已。
-------------------
此回复不是很清晰,请看后面的几位的精彩讲解。谢谢。 否则会引起局部误导。
[解决办法]
很高深,,,,,,来学习............
[解决办法]
代码:
- Java code
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; }}
[解决办法]
[解决办法]
呵呵,很有意思的一个问题!
ArrayList继承自AbstractList,其iterator()方法返回内部类Itr的一个实例,而AbstractList的内部类Itr签名是private
关键问题在最后一行"System.out.print(m.invoke(it));"上
Method的invoke方法参数是一个对象,内部到底决定是谁去调用这个Method呢?这里显然最后JVM决定用T来调用这个"hasNext"的Method对象,T肯定没有访问它的权利,至于底层原理,我会整明白再来回答,呵呵,上班暂时没空
[解决办法]
- Java code
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();}
[解决办法]
原因我找到了,是package的问题,请看如下代码:
下面是3个模仿的类,用于测试,请注意其package为 a
- Java code
package a;public interface MyCollection { public MyIterator myIterator();}
[解决办法]
mark
[解决办法]
会不会 先顶在说!
[解决办法]
Itr是一个inner Class
[解决办法]
[解决办法]
mark,学习
[解决办法]
学习一下……
[解决办法]
[解决办法]
trueException in thread "main" java.lang.IllegalAccessException: Class Test can not access a member of class java.util.AbstractList$Itr with modifiers "public"
[解决办法]
mark
[解决办法]
看了 半天 晕乎!!
[解决办法]
第一次的类是T,调用T的方法时,打印True;
第二次的类是AbstractList,这个类里没有hasNext这个方法,所以抛出异常,但把hasNext改成AbstractList里有的方法就OK了。
[解决办法]
看了 半天 晕乎!!
[解决办法]
真晕阿 看不太懂
[解决办法]
受教了
[解决办法]
学习。。。
[解决办法]
呵呵,老紫竹真敬业!佩服一下……
现在可以把注意力几种在Package之间访问权限的判别机制问题上了!有待进一步研究……
受教学习了!
[解决办法]
呵呵 头有点晕了
[解决办法]
感觉是私有内部类在反射时的访问权限问题,同包可以访问到,不同包则不能,与普通的私有域有区别。
public的内部类不会出现上述问题。
[解决办法]
我想结果大家运行一下代码就都很清楚了,那么出现该问题的原因是什么呢?
这里出现 IllegalAccessException 异常的原因就是java.util.AbstractList$Itr
这个内部类不是公共的,它来自另外一个包:访问位于其他包中的非公共类型的成员是不合法的,这当然包括外部类中的私有内部类,
无论是一般的访问还是通过反射的访问,上述的禁律都是有效的。
那么使用反射又如何调用呢?这是提供用两种方法:
1.取消反射时的安全机制检查
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");
m.setAccessible(true);//注意这句
System.out.print(m.invoke(it));
}
public boolean hasNext() {
return true;
}
}
2.用内部类实现的接口构造Method对象
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 = Iterator.class.getMethod("hasNext");//注意这句
System.out.print(m.invoke(it));
}
public boolean hasNext() {
return true;
}
}
[解决办法]
第二种方法也可以充分说明,虽然内部类是私用的,但它的公共方法在其它包内调用是没有任何问题的.只是调用时不能用原始类型(不可见),必须向上转型后才可调用.
[解决办法]
附整理后的新的测试代码,配合我13楼的代码
- Java code
package b;import java.lang.reflect.Method;import a.MyArrayList;import a.MyCollection;import a.MyIterator;/*** * @author 赵学庆 <A href="http://www.java2000.net/" target=_blank>www.java2000.net</A>* @thanks Ant_Yan xunyiren**/public class TestInvoke { public static void main(String[] args) throws Exception { test1(); test2(); test3(); } public static void test1() { MyCollection t = new MyArrayList(); MyIterator sam = t.myIterator(); Method m; try { m = sam.getClass().getMethod("myHasNext"); m.invoke(sam); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void test2() { MyCollection t = new MyArrayList(); MyIterator sam = t.myIterator(); Method m; try { m = sam.getClass().getMethod("myHasNext"); m.setAccessible(true); // 此处设置了取消安全检测 m.invoke(sam); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void test3() { MyCollection t = new MyArrayList(); MyIterator sam = t.myIterator(); Method m; try { m = MyIterator.class.getMethod("myHasNext"); // 此处使用了接口自身 m.invoke(sam); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }}