Reflecting a class with only package level access

时间:2015-05-12 23:08:21

标签: java reflection

I'm not quite sure how to go about reflecting a class that only has package-level access. I know how to reflect any class that has public access, but I cannot figure out how to reflect the following example:

public func addActivityIndicatorToView(activityIndicator: UIActivityIndicatorView, view: UIView){

    //activityIndicator configuration ...
    activityIndicator.center = view.center
    view.addSubview(activityIndicator)
    activityIndicator.startAnimating()
}

======================

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

======================

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!");}
}

======================

package one;
// abstract class for mimicking android api
abstract class one {
    public void doIt();
    public void dontDoIt();
}

As you can see, the class package one; // empty class for mimicking android api public class test {} only has package-level access. This makes reflecting the class difficult for me. I continue to get compiler errors that states:

one

I've reviewed a few posts, to solve this on my own, but even after reading most of the "similar questions", reading the Main.java:4: error: oneimpl is not public in one; cannot be accessed from outside package oneimpl o = con.newInstance(t); api, and reading generic reflection procedures it's still unclear to me how to achieve this.

Ultimately what I am trying to do is to reflect particular portions of the API to build objects so that soot/spark can build a proper call graph. I'm not actually working inside the android API.

2 个答案:

答案 0 :(得分:3)

您需要在每一步都使用反射,以便做您正在尝试做的事情。

首先,由于您无法从包外部直接引用包one中的包范围类,因此您需要动态加载该类(还要注意{{1}的使用而不是直接使用?):

oneimpl

然后你可以得到构造函数和Class<?> oneImplClass = Class.forName("one.oneimpl"); 方法(确保你将这两个方法都设置为可访问,否则你会得到运行时错误):

doIt

接下来,实例化该类。由于您无法直接引用该类,因此您必须将其强制转换为Constructor<?> constructor = oneImplClass.getDeclaredConstructor(test.class); constructor.setAccessible(true); Method doIt = oneImplClass.getDeclaredMethod("doIt"); doIt.setAccessible (true);

Object

最后,您可以调用Object oneImpl = (Object) constructor.newInstance(); 方法:

doIt

最后一点:在命名类时应遵循Java命名约定:doIt.invoke(oneImpl); 应为oneimplOneImpl应为test。否则Test之类的东西最终看起来像包名而不是完全限定的类名。

答案 1 :(得分:0)

.flush-bottom {
    -fx-padding: 0.416667em 0.5em 0em 0.5em; /* 5 6  0 6 */
}