【问题标题】:How to access a constructor with default access modifier in Java 7 [duplicate]如何在 Java 7 中使用默认访问修饰符访问构造函数 [重复]
【发布时间】: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


【解决方案1】:

默认构造函数

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

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

说(部分)

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

【讨论】:

    猜你喜欢
    • 2012-11-12
    • 2014-03-27
    • 2014-04-01
    • 2017-01-12
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 2016-05-09
    • 2010-09-20
    相关资源
    最近更新 更多