Android 中的反射不起作用

发布于 2024-12-14 10:06:48 字数 2115 浏览 1 评论 0原文

我尝试使用反射来为目标 api 级别为 7 的应用程序使用自定义列表视图。必要的字段仅可从 api 级别 9 获得,因此我尝试通过反射来修复该问题。

我需要找到受保护的方法 View.overScrollBy( int,int,int,int,int,int,int,int,boolean) 。当我调用

View.getDeclaredMethods() 

并迭代 Method[] 数组时,我找到了它,但是当我尝试时,

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

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

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;
    }
}

我不明白为什么第一次调用总是有效,而第二次则不行。有趣的是,当我仅调用一次 View.class.getDeclaredMethod(String name, Class... paramTypes) 时,它也会失败,并且无论我使用硬编码输入值还是从中提取的输入值都没有任何区别我正在寻找的方法...

有人知道问题是什么吗?谢谢

I tried using reflection to use a custom List View for an App with target api level 7. The necessary fileds are only available from api level 9 so I attempted to fix that via reflection.

I need to find the protected Method View.overScrollBy( int,int,int,int,int,int,int,int,boolean). When i call

View.getDeclaredMethods() 

and iterate over the Method[] array i find it, but when I try

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

I get a NoSuchMethodException. I compared the hard coded Method Name and parameterType values with the values extracted from the method (found via iteration) and they are identical...

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;
    }
}

I do not understand why the call always works the first time and the does not the second time. Interestingly it also fails when i call only once for View.class.getDeclaredMethod(String name, Class...< ? > paramTypes) and it does not make any difference whether i use the hard coded input values or the one extracted from the method I am looking for...

Does anybody know what the problem is? Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

笑饮青盏花 2024-12-21 10:06:48

这很有趣,但我认为它不是 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(); 正如 Gray 建议的那样。现在运行正常,但在调试模式下抛出异常。这意味着返回的数组 m 的方法顺序不同。
  • 更新 #2 已确认,我包含了一个 for 循环来打印方法名称。在运行模式下,方法数组的顺序与调试模式相反。

This is very interesting, but it is not Android-specific, I think.

I wrote this small test in plain 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){

        }
    }

In eclipse, if I debug it, the three m1,m2 and m3 are printed. However, if I run it, a NoSuchMethodException is thrown when trying to get m3.

UPDATES:

  • Tested running with jre 7 under linux, and all three m1,m2 and m3 were printed. Perhaps is a problem with jre6? Or is eclipse run configuration?
  • Changed carr declaration to use method 0 instead of 1: Class<?>[] carr = m[0].getParameterTypes(); as Gray suggested. Now it runs ok but throws exception in debug mode. This means different method order for the returned array m.
  • Update #2 confirmed, I've included a for loop to print the method names. In run mode the order of the method array is reversed compared to debug mode.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文