java 为什么不能通过反射找到带有布尔参数的方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5166891/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 09:47:05  来源:igfitidea点击:

Why can a method with a boolean parameter not be found via reflection?

javareflection

提问by Janusz

I'm playing around with some reflection calls to call a method that is normally hidden from me.

我正在玩一些反射调用来调用通常对我隐藏的方法。

I know that this isn't good behaviour but as I said im playing around.

我知道这不是好的行为,但正如我所说的那样。

I used this code to retrieve and invoke the method:

我使用此代码来检索和调用该方法:

ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

setData = ConnectivityManager.class.getDeclaredMethod("setMobileDataEnabled", Boolean.class);
setData.setAccessible(true);
setData.invoke(cm, false);

This gives me this Exception:

这给了我这个例外:

03-02 12:21:40.411: ERROR/test(1052): java.lang.NoSuchMethodException: setMobileDataEnabled
03-02 12:21:40.411: ERROR/test(1052):     at java.lang.ClassCache.findMethodByName(ClassCache.java:308)
03-02 12:21:40.411: ERROR/test(1052):     at java.lang.Class.getDeclaredMethod(Class.java:748)

Then i tried to see if the method is declared in the class and tried this to find all methods and invoke the wanted method:

然后我尝试查看该方法是否在类中声明并尝试使用此方法查找所有方法并调用所需的方法:

ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

Method[] methods = cm.getClass().getMethods();
for (Method method : methods) {
   Log.d(Test.class.getSimpleName(), "Method name is: " + method.getName());
   if (method.getName().equals("setMobileDataEnabled")) {
      Log.d(Test.class.getSimpleName(), "Found method calling");
       method.setAccessible(true);
       method.invoke(cm, false);
   }
}

This gives me the following output:

这给了我以下输出:

03-02 12:19:41.851: DEBUG/Test(980): Method name is: getActiveNetworkInfo
03-02 12:19:41.851: DEBUG/Test(980): Method name is: getAllNetworkInfo
03-02 12:19:41.851: DEBUG/Test(980): Method name is: getBackgroundDataSetting
03-02 12:19:41.851: DEBUG/Test(980): Method name is: getLastTetherError
03-02 12:19:41.861: DEBUG/Test(980): Method name is: getMobileDataEnabled
03-02 12:19:41.861: DEBUG/Test(980): Method name is: getNetworkInfo
03-02 12:19:41.861: DEBUG/Test(980): Method name is: getNetworkPreference
03-02 12:19:41.861: DEBUG/Test(980): Method name is: getTetherableIfaces
03-02 12:19:41.861: DEBUG/Test(980): Method name is: getTetherableUsbRegexs
03-02 12:19:41.861: DEBUG/Test(980): Method name is: getTetherableWifiRegexs
03-02 12:19:41.861: DEBUG/Test(980): Method name is: getTetheredIfaces
03-02 12:19:41.871: DEBUG/Test(980): Method name is: getTetheringErroredIfaces
03-02 12:19:41.871: DEBUG/Test(980): Method name is: isTetheringSupported
03-02 12:19:41.871: DEBUG/Test(980): Method name is: requestRouteToHost
03-02 12:19:41.871: DEBUG/Test(980): Method name is: setBackgroundDataSetting
03-02 12:19:41.871: DEBUG/Test(980): Method name is: setMobileDataEnabled
03-02 12:19:41.871: DEBUG/Test(980): Found method calling
03-02 12:19:41.871: DEBUG/ConnectivityService(127): setMobileDataEnabled(false)
03-02 12:19:41.891: DEBUG/ConnectivityService(127): getMobileDataEnabled returning true
03-02 12:19:41.931: ERROR/Test(980): InvocationTargetException
03-02 12:19:41.931: ERROR/Test(980): java.lang.reflect.InvocationTargetException
03-02 12:19:41.931: ERROR/Test(980):     at android.net.ConnectivityManager.setMobileDataEnabled(ConnectivityManager.java:379)
03-02 12:19:41.931: ERROR/Test(980):     at java.lang.reflect.Method.invokeNative(Native Method)
03-02 12:19:41.931: ERROR/Test(980):     at java.lang.reflect.Method.invoke(Method.java:521)
03-02 12:19:41.931: ERROR/Test(980):     at Test(Test.java:84)

This output shows me that the Methodis there and I can call it despite the fact that the Android sanity check kicks in and forbids the calling of the deeper system methods.

Method尽管 Android 健全性检查已启动并禁止调用更深层次的系统方法,但此输出显示存在并且我可以调用它。

Why is it that the method is not found via getDeclaredMethod?

为什么找不到方法 via getDeclaredMethod

回答by Michael Borgwardt

Two possible causes of this problem, can't say which without knowning the source:

这个问题的两个可能原因,在不知道来源的情况下不能说:

  • Is the parameter type actually Booleanand not boolean? Different types, potentially different overloaded methods, which is why literals like boolean.classexist and have to be used here.
  • Is the method inherited? getDeclaredMethod()only looks at the class's own methods, not those that have been inherited. You'll have to iterate through the class hierarchy to get inherited methods.
  • 参数类型实际上是Boolean不是boolean?不同的类型,可能不同的重载方法,这就是为什么像这样的文字boolean.class存在并且必须在这里使用。
  • 方法是继承的吗?getDeclaredMethod()只看类自己的方法,而不是那些已经被继承的方法。您必须遍历类层次结构以获取继承的方法。

回答by Sean Patrick Floyd

In the Question title, you write boolean(lower case), but in your code, you search for Boolean(upper case). Try this if the parameter type is boolean(primitive):

在问题标题中,您编写boolean(小写),但在您的代码中,您搜索Boolean(大写)。如果参数类型为boolean(原始),请尝试此操作:

setData = ConnectivityManager.class.getDeclaredMethod(
          "setMobileDataEnabled", boolean.class);

回答by Melv

Is setMobileDataEnabledon ConnectivityManager or a parent class? Looking at getDeclaredMethod, I think it needs to be on the class itself, whereas getMethod gets methods from the entire inheritance tree.

setMobileDataEnabled在 ConnectivityManager 还是父类上?看一下getDeclaredMethod,我认为它需要在类本身上,而getMethod从整个继承树中获取方法。

回答by Android

Put the proper uses permissions in the AndroidManifest.xml

将正确的使用权限放在 AndroidManifest.xml 中

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />

The problem you are having is a security issue.

您遇到的问题是安全问题。