有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Android中的java反射不起作用

我尝试使用反射为目标api级别为7的应用程序使用自定义列表视图。必要的文件只能从api级别9获得,所以我尝试通过反射来修复它

我需要找到受保护的方法视图。overScrollBy(int,int,int,int,int,int,int,int,int,boolean)。当我打电话时

View.getDeclaredMethods() 

然后迭代方法[]数组,我找到了它,但是当我尝试

View.class.getDeclaredMethod(String name, Class...< ? > paramTypes)

我有个例外。我将硬编码的方法名称和参数类型值与从方法中提取的值(通过迭代找到)进行了比较,它们是相同的

private boolean initCompatibility() 
{
Method[] methods = View.class.getDeclaredMethods();
try {
    // The name of the Method i am looking for;
    String OVERSCROLL_S = "overScrollBy";
    for (Method meth : methods) {
        if (meth.getName().equals(OVERSCROLL_S)) {
            mListView_overScrollBy = meth;
            break;
            // method found
        }
    }

    // Params for getDeclaredMethod(…)
    String methodName = "overScrollBy";
    Class[] methodParams =  {  Integer.TYPE, Integer.TYPE, Integer.TYPE, 
            Integer.TYPE, Integer.TYPE, Integer.TYPE, Integer.TYPE, 
            Integer.TYPE, Boolean.TYPE };

    // works
    Method test =  View.class.getDeclaredMethod(methodName,methodParams);
    // fails
    View.class.getDeclaredMethod(mListView_overScrollBy.getName(), 
               mListView_overScrollBy.getParameterTypes());

    /*
    * I also tried this way around and again the first worked and the second
    * failed, so the input arguments are not the problem...
    * View.class.getDeclaredMethod( mListView_overScrollBy.getName(), 
    *                           mListView_overScrollBy.getParameterTypes() );
    * Method test =  View.class.getDeclaredMethod(methodName,methodParams);
    */

    return true;
    } catch (SecurityException e) {
        e.printStackTrace();
        return false;
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
        return false;
    }
}

我不明白为什么第一次呼叫总是有效,第二次呼叫总是无效。有趣的是,当我只打一次电话来查看时,它也失败了。班getDeclaredMethod(String name,Class…<;?>;paramTypes),无论我使用的是硬编码输入值还是从我要查找的方法中提取的输入值,都没有任何区别

有人知道问题出在哪里吗?谢谢


共 (1) 个答案

  1. # 1 楼答案

    这很有趣,但我认为它不是Android特有的

    我用纯Java编写了这个小测试:

        public class ReflectionTest {
    
            public static void main(String[] args){
                Method[] m = ReflectionTest.class.getDeclaredMethods();
                for (Method method : m) {
                    System.out.println(method.getName());
                }               
    
                try {
                    Method m1 = ReflectionTest.class.getDeclaredMethod("d0", int.class, boolean.class);
                    if(m1 != null){
                        System.out.println("m1 found!");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } 
    
                try {
                    Method m2 = ReflectionTest.class.getDeclaredMethod("d0", Integer.TYPE, Boolean.TYPE);
                    if(m2 != null){
                        System.out.println("m2 found!");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } 
    
                try {
                    Class<?>[] carr = m[1].getParameterTypes();
                    Method m3 = ReflectionTest.class.getDeclaredMethod("d0", carr);
                    if(m3 != null){
                        System.out.println("m3 found!");
                    }
                } catch (Exception e){
                    e.printStackTrace();
                } 
            }
    
            public void d0(int a, boolean b){
    
            }
        }
    

    在eclipse中,如果我调试它,将打印三个m1、m2和m3。但是,如果我运行它,在尝试获取m3时会抛出一个NoSuchMethodException

    更新:

    • 在linux下用jre 7测试运行,所有三个m1、m2和m3都被打印出来。也许jre6有问题?或者eclipse是运行配置吗
    • 更改了carr声明以使用方法0,而不是格雷建议的方法1:Class<?>[] carr = m[0].getParameterTypes();。现在它运行正常,但在调试模式下抛出异常。这意味着返回的数组m的方法顺序不同
    • 更新#2已确认,我已包含一个for循环来打印方法名称。在运行模式下,方法数组的顺序与调试模式相反