我不太确定如何反映一个只有包级访问权限的类。我知道如何反映任何具有公共访问权限的类,但我无法弄清楚如何反映以下示例:
public class Main {
public static void main(String[] args) {
test t = new test();
Constructor<one.oneimpl> con = one.oneimpl.class.getDeclaredConstructor(test.class);
oneimpl o = con.newInstance(t);
o.doIt();
}
}
Run Code Online (Sandbox Code Playgroud)
======================
package one;
// implementation class for mimicking android api
class oneimpl extends one {
Test mTest;
private oneimpl(test t){mTest = t;}
public void doIt(){System.out.println("Do It!");}
public void dontDoit(){System.out.println("Don't Do It!");}
}
Run Code Online (Sandbox Code Playgroud)
======================
package one;
// abstract class for mimicking android api
abstract class one {
public void doIt();
public void dontDoIt();
}
Run Code Online (Sandbox Code Playgroud)
======================
package one;
// empty class for mimicking android api
public class test {}
Run Code Online (Sandbox Code Playgroud)
如您所见,该类one仅具有包级别的访问权限。这让我很难反映课堂。我继续收到编译器错误,指出:
Main.java:4: error: oneimpl is not public in one; cannot be accessed from outside package
oneimpl o = con.newInstance(t);
Run Code Online (Sandbox Code Playgroud)
我已经查看了一些帖子,以自己解决这个问题,但即使在阅读了大部分“类似问题”、阅读AccessibilityObjectapi 和通用反射程序之后,我仍然不清楚如何实现这一点。
最终我想要做的是反映 API 的特定部分来构建对象,以便 soot/spark 可以构建正确的调用图。我实际上并没有在 android API 中工作。
你需要在每一步都使用反射来做你想做的事情。
首先,由于您不能one从该包外部直接引用包中的包范围类,因此您需要动态加载该类(还要注意使用?代替 直接使用oneimpl):
Class<?> oneImplClass = Class.forName("one.oneimpl");
Run Code Online (Sandbox Code Playgroud)
然后你可以得到构造函数和doIt方法(确保你将它们都设置为可访问,否则你会得到运行时错误):
Constructor<?> constructor = oneImplClass.getDeclaredConstructor(test.class);
constructor.setAccessible(true);
Method doIt = oneImplClass.getDeclaredMethod("doIt");
doIt.setAccessible (true);
Run Code Online (Sandbox Code Playgroud)
接下来,实例化类。您必须将其强制转换为,Object因为您无法直接引用该类):
Object oneImpl = (Object) constructor.newInstance();
Run Code Online (Sandbox Code Playgroud)
最后,您可以调用该doIt方法:
doIt.invoke(oneImpl);
Run Code Online (Sandbox Code Playgroud)
最后要注意的是:在命名类时应该遵循 Java 命名约定:oneimplshould beOneImpl和testshould be Test。否则one.oneimpl最终看起来像包名而不是完全限定的类名。