`
逆风的香1314
  • 浏览: 1390393 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

反射调用私有实现类的方法出异常的分析

阅读更多

原始内容如下:

http://www.java2000.net/viewthread.jsp?tid=6982

http://topic.csdn.net/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 src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"> </script>
分享到:
评论

相关推荐

    JAVA反射机制动态调用 计算器对象的加法,减法函数;JAVA反射机制修改一个学生对象 的私有数据成员

    使用JAVA反射机制动态调用 计算器对象的加法,减法函数。 使用JAVA反射机制修改一个学生对象 的私有数据成员(不允许调用setters) 使用的类有Class, Method, Field

    C++访问类中私有成员变量的方法

    原则上,C++类中私有变量不允许在类之外的其他任何地方访问,一般来说功能完善的类都会提供get,set方法来操作类属性值,还有是是通过友元访问。但是!但如果没有get、set方法都没有提供,也没有定义友元,比如使用...

    基础深化和提高-java反射技术

    Java反射技术指的是在运行时动态地获取类的信息、调用对象的方法、操作类的属性等能力。通过反射,程序可以在运行时检查类、实例化对象、调用方法、获取和设置属性,甚至可以动态修改类的结构。 Java反射技术的核心...

    Java 反射机制详解

    Java 反射机制详解,适合初学者 1.获取 对象建模类的类型 的方法: 2.获取类中定义的构造方法: 获取类中定义的方法 获取类中定义的属性: 3.获取类实现的接口 4.利用反射实现类: 5.调用私有方法

    jTester使用指南(带书签).pdf

    第 6 章 反射调用私有方法或JDK代理的方法 调用私有方法 访问私有变量 使用反射方式构造对象实例 第 7 章 在测试代码中使用Mock 静态mock,new MockUp的使用 mock构造函数和静态代码块 new MockUp和spring的...

    你不知道的JAVA高级应用

    3.动态代理 在调用这个目标方法前,后,2头,异常处都可以动态的加上自己需要逻辑判断,而且根据反射来动态的替换实现类,大大提升了程序的灵活性 4.拆箱装箱的中的项元模式,当该对象在一个字节内时 -128~~127 的时候 用...

    CLR.via.C#.(中文第3版)(自制详细书签)Part2

    20.5 抛出异常 20.6 定义自己的异常类 20.7 用可靠性换取开发效率 20.8 指导原则和最佳实践 20.8.1 善用finally块 20.8.2 不要什么都捕捉 20.8.3 得体地从异常中恢复 20.8.4 发生不可恢复的异常时回滚部分...

    easybus:没有反射的快速事件总线

    我见过的所有实现的主要缺点是它们都使用反射来调用侦听器方法,即Method.invoke() 。 不幸的是,这种方法在低延迟世界中是不可接受的,因此我决定使用优秀的 OpenHFT/Java-Runtime-Compiler 库来代替在运行时为...

    CLR.via.C#.(中文第3版)(自制详细书签)Part1

    20.5 抛出异常 20.6 定义自己的异常类 20.7 用可靠性换取开发效率 20.8 指导原则和最佳实践 20.8.1 善用finally块 20.8.2 不要什么都捕捉 20.8.3 得体地从异常中恢复 20.8.4 发生不可恢复的异常时回滚部分...

    CLR.via.C#.(中文第3版)(自制详细书签)

    20.5 抛出异常 20.6 定义自己的异常类 20.7 用可靠性换取开发效率 20.8 指导原则和最佳实践 20.8.1 善用finally块 20.8.2 不要什么都捕捉 20.8.3 得体地从异常中恢复 20.8.4 发生不可恢复的异常时回滚部分...

    Java开发技术大全(500个源代码).

    invokeMethod.java 同一个类中调用方法示例 invokeOther.java 类的外部调用方法示例 invokeStaticMethod.java 调用静态方法示例 localVariable.java 演示局部变量 localVSmember.java 局部变量与成员变量同名...

    CLR.via.C#.(中文第3版)(自制详细书签)Part3

    20.5 抛出异常 20.6 定义自己的异常类 20.7 用可靠性换取开发效率 20.8 指导原则和最佳实践 20.8.1 善用finally块 20.8.2 不要什么都捕捉 20.8.3 得体地从异常中恢复 20.8.4 发生不可恢复的异常时回滚部分...

    易语言伪反射特性实例-易语言

    很多功能均为实现,如通用型类的绑定、数据对象与数据库的实时保存、私有成员的通用数据类型等 实现的意义:只需编写对象,加几行代码即可快速实现超级列表框的增删改 其他功能请发挥自己的想象力 1、编写一个...

    javaSE代码实例

    11.3.4 方法重写对抛出异常声明的约束 210 11.4 定义自己的异常 212 11.4.1 创建自己的异常类 212 11.4.2 使用自定义的异常类 213 11.4.3 显性再抛出作用的体现 215 11.5 异常的匹配 217 11.5.1 同时...

    JAVA面试题最全集

    51.Object类(或者其子类)的finalize()方法在什么情况下被调用? 52.一个“.java”原文件中是否可以包括多个类(不是内部类)? 53.掌握内部类和接口的概念 54.StringTokenizer类的使用 55.数据结构,如何遍历...

    asp.net知识库

    通过反射调用類的方法,屬性,字段,索引器(2種方法) ASP.NET: State Server Gems 完整的动态加载/卸载程序集的解决方案 从NUnit中理解.NET自定义属性的应用(转载) 如何在.NET中实现脚本引擎 (CodeDom篇) .NET的插件...

    21天学通Java-由浅入深

    225 11.3 抛出异常 225 11.3.1 抛出异常的简单介绍 225 11.3.2 使用throws和throw语句抛出异常 227 11.4 自定义异常 227 11.4.1 创建和使用自定义异常类 227 11.4.2 自定义异常的实际应用 228 11.5 综合练习 231 ...

    day020-继承加强和设计模式代码和笔记.rar

    概念:就是类中只有(静态、非静态)方法,就是为了调用方法。 2. 作用:就是一个轮子 3. 分类: 1. 静态的 方法全部都是static修饰的,调用方式:类名.方法名(...); 2. 非静态的 通过单例...

Global site tag (gtag.js) - Google Analytics