【发布时间】:2015-10-08 10:11:58
【问题描述】:
我问过一个类似的问题,但我过早地接受了答案。又来了。
背景: 我正在尝试通过它的坐标实例化我作为 Maven 依赖项导入的类的构造函数。
问题: 我遇到的问题是这个类的特定构造函数对我来说是不可见的,因为它没有与之关联的访问修饰符,所以它是默认的,这意味着我无法从外部访问它。
示例: 我正在尝试使用的课程在这里:
public class SomeClass {
// Notice no access modifier here so it's package-default
SomeClass(Log log, File in, File out) {
some stuff ...
}
// public constructor
public SomeClass() {}
// Method 1
public void compiler(File schema) {
some stuff ...
}
// Method 2
public void linker(File attribute) {
some stuff ...
}
}
这是我在一个单独项目中的顶层:
public class TopLevel {
public void testSomeClass() {
Constructor<SomeClass> constructor = SomeClass.class.getDeclaredConstructor(Log.class, File.class, File.class);
constructor.setAccessible(true);
// Default access level
SomeClass builder = constructor.newInstance(log, contentDirectory, outputDirectory);
//Here is where the problem occurs
builder.compiler(schemaFile);
}
}
评论: 这似乎不起作用,上面的实现在我的顶层,构造函数和类中的方法现在对我都是可见的,我可以调用它们但是我从 ReflectiveCallable 抽象方法向我抛出了一个异常,该方法在调用时, 从反射的方法中抛出异常,而不是将其包装在 InvocationTargetException 中。类 DecisionTableBuilder 的实例化方式似乎有问题。因此我的问题在这里。
我这样做对吗?是否有另一种方法来反映默认访问修改的构造函数/方法?当我显式反映构造函数时,我是否也需要反映类方法?
任何帮助都将不胜感激。提前谢谢大家
编辑:
这是我的堆栈跟踪,如果有人能理解的话......
java.lang.NullPointerException
at com.intuit.ctg.tla.compilers.SomeClass.compile(SomeClass.java:95)
at com.intuit.ctg.tla.compilers.qa.testSomeClass.testSomeClass(testCompilerLinker.java:80)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
我已经按照这个堆栈跟踪到这行代码:
// This piece of code recursively searches in directory treesDirectory and
// lists all file with xml extentions
Collection<File> flowchartFiles = FileUtils.listFiles(treesDirectory, mapExtension, true);
即使我通过构造函数传递它,treesDirectory(类型文件)也得到一个 NULL 指针,这里作为第二个参数:
public static File treesDirectory = new File("src/test/resources/input_graphs/");
public static File outputDirectory = new File("src/test/resources/output");
public static Log log;
SomeClass builder = constructor.newInstance(log, treesDirectory, outputDirectory);
反射构造函数中发生了一些有趣的事情......有人有什么想法吗?我已经坚持了 2 天了...
【问题讨论】:
-
请发布一个完整且可重现的示例和异常的完整堆栈跟踪(如果有的话)。
-
AFAIK 构造函数是故意对你隐藏的,没有合法的访问方式。这就是人们分发软件的方式。
-
@Sreekar 这是 Java 反射的目的,让您可以访问私有和默认访问修改的构造函数和方法
-
我同意,有人要求提供更多详细信息。我将删除一些代码以使其不那么冗长
-
如果您的错误确实发生在最后一行,您已经设法获得了
DecisionTableBuilder的实例,那么我认为反射不再是一个问题。但是如果没有正确的错误消息和堆栈跟踪,这一切都是猜测。
标签: java maven reflection access-modifiers