利用java反射调用类的的私有方法--转

原文:http://blog.csdn.net/woshinia/article/details/11766567

1,今天和一位朋友谈到父类私有方法的调用问题,本来以为利用反射很轻松就可以实现,因为在反射看来根本不区分是否是private的,没有想到调用本身的私有方法是可以的,但是调用父类的私有方法则不行,后来纠其原因很有可能是因为getDeclaredMethod方法和getMethod方法并不会查找父类的私有方法,于是只好自己写递归了,经过尝试果然如此。把代码放出来方便更多人。这段代码可以解决很多实际问题,不过利用反射来做的话性能不会太好。

[java] view plaincopy
 
 
  1. package com.syj.util.reflect;  
  2.   
  3. import java.lang.reflect.Method;  
  4.   
  5. /** 
  6.  * <p> 
  7.  * Title: 私有方法调用工具类 
  8.  * </p> 
  9.  *  
  10.  * <p> 
  11.  * Description:利用java反射调用类的的私有方法 
  12.  * </p> 
  13.  *  
  14.  * <p> 
  15.  * Copyright: Copyright (c) 2007 
  16.  * </p> 
  17.  *  
  18.  * @author 孙钰佳 
  19.  * @main sunyujia@yahoo.cn 
  20.  * @date Jun 1, 2008 10:18:58 PM 
  21.  */  
  22. public class PrivateUtil {  
  23.     /** 
  24.      * 利用递归找一个类的指定方法,如果找不到,去父亲里面找直到最上层Object对象为止。 
  25.      *  
  26.      * @param clazz 
  27.      *            目标类 
  28.      * @param methodName 
  29.      *            方法名 
  30.      * @param classes 
  31.      *            方法参数类型数组 
  32.      * @return 方法对象 
  33.      * @throws Exception 
  34.      */  
  35.     public static Method getMethod(Class clazz, String methodName,  
  36.             final Class[] classes) throws Exception {  
  37.         Method method = null;  
  38.         try {  
  39.             method = clazz.getDeclaredMethod(methodName, classes);  
  40.         } catch (NoSuchMethodException e) {  
  41.             try {  
  42.                 method = clazz.getMethod(methodName, classes);  
  43.             } catch (NoSuchMethodException ex) {  
  44.                 if (clazz.getSuperclass() == null) {  
  45.                     return method;  
  46.                 } else {  
  47.                     method = getMethod(clazz.getSuperclass(), methodName,  
  48.                             classes);  
  49.                 }  
  50.             }  
  51.         }  
  52.         return method;  
  53.     }  
  54.   
  55.     /** 
  56.      *  
  57.      * @param obj 
  58.      *            调整方法的对象 
  59.      * @param methodName 
  60.      *            方法名 
  61.      * @param classes 
  62.      *            参数类型数组 
  63.      * @param objects 
  64.      *            参数数组 
  65.      * @return 方法的返回值 
  66.      */  
  67.     public static Object invoke(final Object obj, final String methodName,  
  68.             final Class[] classes, final Object[] objects) {  
  69.         try {  
  70.             Method method = getMethod(obj.getClass(), methodName, classes);  
  71.             method.setAccessible(true);// 调用private方法的关键一句话  
  72.             return method.invoke(obj, objects);  
  73.         } catch (Exception e) {  
  74.             throw new RuntimeException(e);  
  75.         }  
  76.     }  
  77.   
  78.     public static Object invoke(final Object obj, final String methodName,  
  79.             final Class[] classes) {  
  80.         return invoke(obj, methodName, classes, new Object[] {});  
  81.     }  
  82.   
  83.     public static Object invoke(final Object obj, final String methodName) {  
  84.         return invoke(obj, methodName, new Class[] {}, new Object[] {});  
  85.     }  
  86.   
  87.     /** 
  88.      * 测试反射调用 
  89.      *  
  90.      * @param args 
  91.      */  
  92.     public static void main(String[] args) {  
  93.         PrivateUtil.invoke(new B(), "printlnA", new Class[] { String.class },  
  94.                 new Object[] { "test" });  
  95.         PrivateUtil.invoke(new B(), "printlnB");  
  96.     }  
  97. }  
  98.   
  99. class A {  
  100.     private void printlnA(String s) {  
  101.         System.out.println(s);  
  102.     }  
  103. }  
  104.   
  105. class B extends A {  
  106.     private void printlnB() {  
  107.         System.out.println("b");  
  108.     }  
  109. }  


程序的输出结果为
test
b
说明private方法调用成功了不管是自己的私有方法还是父类的私有方法。

2,

[java] view plaincopy
 
  1. package me.test;  
  2. import java.lang.reflect.*;  //导入反射需要的包  
  3. public class ReflectTest {  
  4.  public static void main(String[] args)  throws  Exception  
  5.  {    
  6.     
  7.   /*  下面通过反射完成对一个对象中成员的替换 
  8.    *   并且执行执行私有方法   
  9.    *   完成对 Poiont类的对象中所有的 String的对象的d换成x 
  10.    *   并且类中无修改方法     
  11.    */   
  12.     Point pt=new Point(3,5);  //创建一个Point对象  
  13.     Field fx=pt.getClass().getField("x") ;  //获取x的映射类对象  
  14.     Field fy=pt.getClass().getDeclaredField("y");//因为y是私有的所以要调用这个方法   
  15.     Method m2=Point.class.getDeclaredMethod("showPrivate") ;//获得私有方法映射类    
  16.       
  17.     //利用反射调用共有输出   
  18.     m2.setAccessible(true)  ;// 修改showPrivate 权限 改变为可以调用  
  19.        m2.invoke(pt) ;//执行私有方法  
  20.     //利用成员反射输出x 和 私有的 y    
  21.     System.out.println(fx.getInt(pt));//反射输出x    
  22.     fy.setAccessible(true) ;//改变私有为可访问  
  23.     System.out.println(fy.getInt(pt));//输出私有y  
  24.           
  25.     //替换成员后并且反射私有方法输出   
  26.     changeString(pt) ;//反射替换成员值  
  27.      System.out.println(pt);  
  28.       
  29.       
  30.  }  
  31.  public static void changeString(Object obj)  throws Exception//反射替换对所有String进行替换  
  32.  {   
  33.   Field[] f=obj.getClass().getFields()  ; //获得成员映射数组  
  34.   for(Field tem : f)  //迭代for循环  
  35.   {  
  36.    if(tem.getType()==String.class)  //内存中只有一份String字节码   
  37.    {  
  38.     String oldString=(String)tem.get(obj) ;  //返回内容  
  39.     String newString=oldString.replace('d', 'x');//将所有b替换为x    
  40.     tem.setAccessible(true);  
  41.      tem.set(obj, newString) ;//替换成员值  
  42.    }  
  43.      
  44.   }  
  45.     
  46.  }  
  47. }  
  48.   
  49. public class Point  
  50. {  
  51.  public int x  ;  
  52.  private int y  ;  
  53.  public Point(int x, int y) {  
  54.   super();  
  55.   this.x = x;  
  56.   this.y = y;  
  57.  }  
  58.    public String  a="dsfdsfd"  ;  //只有 共有可以替换  
  59.    public String  b="fdsfdsfewewwwww"  ;  
  60.    public String  c="adddssss"  ;  
  61.   
  62.  private void showPrivate()  //私有方法输出  
  63.  {  
  64.   System.out.println("x="+this.x+" "+"y="+this.y);  
  65.   System.out.println(this.a);  
  66.   System.out.println(this.b);  
  67.   System.out.println(this.c);   
  68.  }  
  69.   
  70.  public String toString()  
  71.  {  
  72.   return this.a+" "+this.b+" "+this.c;  
  73.  }  
  74.   
  75. }  


3,  

Java利用反射来获取一个方法的 范型化参数 Vector<Integer>的类型

[java] view plaincopy
 
  1. class   A  
  2.   
  3. {  
  4.   
  5.      public  void   show(Vector<Integer> v)  {}  
  6. }    
  7.   
  8. 在我们不知道Vector中数据的类型的时候 这时候我们只知道这个方法的名字  和参数的个数 ,我们来获取 范型化的实际类型 。   
  9.   
  10. 我们不可能通过 Vector对应的Class类来反射出  泛型集合中的类型  ,但是 我们却可以通过 这个方法所对应的Method类来实现 。  
  11.   
  12. 具体如下  :  
  13.   
  14. import java.lang.reflect.Method;  
  15. import java.lang.reflect.ParameterizedType;  
  16. import java.lang.reflect.Type;  
  17. import java.util.Vector;  
  18.   
  19. public class Test3  
  20. {  
  21.  public static void main(String []args) throws SecurityException, NoSuchMethodException  
  22.  {  
  23.   Method  m=A.class.getMethod("show", Vector.class) ;      //反射获得show方法的Method对象  
  24.   Type[]t=m.getGenericParameterTypes() ;      //获得范型参数的 一个Type数组  Type是Class类的基类 GenericArrayType, ParameterizedType, TypeVariable<D>, WildcardType  这些都是 实现Type的子接口   
  25.   ParameterizedType p=(ParameterizedType)t[0];     //强制转换成Type的子接口 ParameterizedType类型 因为这个接口又可以获得 范型化集合中元素的类型    System.out.println(p.getRawType());                     //获得集合的类型    
  26.   System.out.println(p.getActualTypeArguments()[0]);   //获得集合中元素的类型  
  27.  }  
  28.   
  29. }  
原文地址:https://www.cnblogs.com/mochaMM/p/5016431.html