如何在Java 7中使用默认访问修饰符访问构造函数

时间:2015-07-19 00:56:22

标签: java maven reflection access-modifiers

我问了一个类似的问题,但我过早地接受了答案。这是再次。

上下文 我正在尝试实例化一个类的构造函数,我通过它的坐标将其作为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(类型File)获取一个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天了...

1 个答案:

答案 0 :(得分:1)

默认构造函数

只能由同一个包中的类访问。您可以在该包中创建自己的工厂(或构建器)并为其提供public访问权限。您的API中也可能已经提供了一个。

JLS Example 6.6-4. Access to Default-Access Fields, Methods, and Constructors

说(部分)

  

如果未指定任何访问修饰符publicprotectedprivate,则可以在整个包中访问类成员或构造函数,其中包含类的声明,其中声明了类成员,但是在任何其他包中都无法访问类成员或构造函数。