我试图运行反射来检查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进行编译和运行的。
答案 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;
}
}