Java反射-找不到Android类

时间:2018-12-14 15:52:14

标签: java android reflection

我试图运行反射来检查Java中是否存在某些android类(例如Toast)。我正在使用以下代码从命令行运行它:

String [] packages = new String[] {"java.lang.",
    "android.widget.",
    "android.util.",
    "android.app.",
    "android.view.",
    "android.content."};
for (int i = 0; i < packages.length; i++){
    String package_name = packages[i];
    try {
        Class<?> clazz = Class.forName(package_name + "Toast");
        System.out.println("class Exists");
        return clazz;
    }
    catch (ClassNotFoundException e){
        System.out.println("class " + package_name + "Toast doesnt exists");
    }
}

但是,我得到了输出: 类android.widget.Toast不存在(但是我知道它确实是该类所在的地方) 有什么想法吗?


编辑:我正在尝试编写一个Java类,该类不是从Android Studios运行的,而是使用cmd行中的javac进行编译和运行的。

2 个答案:

答案 0 :(得分:1)

由于您是在命令行上执行此操作,因此除非明确包含Android包/类,否则没有理由对运行时可用。程序的输出很有意义-除非您为程序提供正确的Android库,否则当您尝试解析特定的Android类(例如Toast)时就不会匹配。

答案实际上是有效地使用Java的类路径。默认情况下,不说明参数,而是工作目录“。”。

使用-classpath作为参数添加到它。天真地编译:

javac YourReflectionTest.java

您知道该程序找不到匹配项。

如果您这样做,javac也将成功

javac -classpath ".;/opt/android-sdk/platforms/android-21/android.jar" YourReflectionTest.java

如果您运行该程序,请尝试

java YourReflectionTest

它仍然会产生相同的结果。为什么?在运行时,仍然没有加载Android类。默认情况下,您只会获得JDK安装中包含的Java系统库。

但是,如果您在运行时提供适当的路径,那么突然之间所有魔术都将发生:

java -classpath ".;/opt/android-sdk/platforms/android-21/android.jar" YourReflectionTest

请注意,Android API级别21仅是此处的示例,可以根据要测试的功能使用任何API。

答案 1 :(得分:0)

执行代码时,我得到以下输出:

class java.lang.Toast doesnt exists
class Exists

由于遍历所有软件包,因此无论您的类是否存在,每个软件包都会得到输出,并且只有找到匹配项时才停止。

我认为您要实现的目标是始终仅获得1个输出:类存在或不存在。您可以通过创建方法classExists(),然后使用java流API来查找您的任何软件包是否包含类Toast来做到这一点:

public void myMethod() {
    List<String> packages = Arrays.asList(
            "java.lang.",
            "android.widget.",
            "android.util.",
            "android.app.",
            "android.view.",
            "android.content."
    );
    String className = "Toast";
    if (packages.stream().anyMatch(pkg -> classExists(pkg + className))) {
        System.out.println("class exists");
    } else {
        System.out.println("class doesnt exist");
    }
}

boolean classExists(String fullClassName) {
    try {
        Class.forName(fullClassName);
        return true;
    } catch (ClassNotFoundException e) {
        return false;
    }
}