【问题标题】:How to access a constructor of with default access (or package-default)如何使用默认访问(或包默认)访问构造函数
【发布时间】:2015-10-06 13:22:54
【问题描述】:

我正在尝试实例化一个类的构造函数,该类通过它的坐标作为 Maven 依赖项导入。我遇到的问题是这个类的特定构造函数对我来说是不可见的,因为它没有与之关联的访问修饰符,所以它是默认的,这意味着我无法从外部访问它。

我知道有一种方法可以通过反射访问私有方法,使用类 Method 的 getDeclaredMethod() 方法,但这不适用于构造函数(如果我错了,请纠正我)。

我要使用的类在这里:

public class DecisionTableBuilder {

   // Notice no access modifier here so it's package-default
   DecisionTableBuilder(Log log, File in, File out) {
      some stuff ...
   }

   // public constructor
   public DecisionTableBuilder() {}

   // Method 1
   public void compiler(File schema) {
      some stuff ...
   }

   // Method 2
   public void linker(File attribute) {
      some stuff ...
   }
}

这是我在一个单独项目中的顶层:

public class TopLevel {

   public void testDecisionTableBuilder() {

      // I get an error saying the constructor DecisionTableBuilder is not visible
      DecisionTableBuilder builder = new DecisionTableBuilder();

      // This works just fine, but no constructor...
      DecisionTableBuilder builder2;

      // This doesn't really work
      Method[] m = DecisionTableBuilder.class.getDeclaredMethods("DecisionTableBuilder", "Log", "File", "File");

   }
}

如何访问我在新项目中创建的顶级类中的构造函数和方法?任何帮助将不胜感激

编辑

public File graphDir;
public File outputDir;
public Log log;

Constructor<DecisionTableBuilder> constructor = DecisionTableBuilder.class.getDeclaredConstructor(Log.class,File.class,File.class);
constructor.setAccessible(true);
DecisionTableBuilder builder =constructor.newInstance(log, graphDir, outputDir);

这是正确的吗?

【问题讨论】:

  • 你冒着破坏第三方代码和/或让自己很容易受到其实施变化的影响。
  • 这是有意的,我希望这个代码在依赖类发生变化时中断

标签: java maven reflection access-modifiers


【解决方案1】:

您不能使用getDeclaredMethodgetDeclaredMethods 访问构造函数。 Java 反射机制区分方法和构造函数,并有单独的方法来访问它们。

试试getDeclaredConstructors method

Constructor[] c = DecisionTableBuilder.class.getDeclaredConstructors();

或者对于特定的构造函数,getDeclaredConstructor。传入代表参数类型的Class 对象,而不是类的字符串名称。

Constructor<DecisionTableBuilder> constructor =
    DecisionTableBuilder.class.getDeclaredConstructor(Log.class, File.class, File.class);

您需要将其设置为可访问,然后调用newInstance 来创建DecisionTableBuilder。'

constructor.setAccessible(true);
DecisionTableBuilder dtb = constructor.newInstance(yourLog, inFile, outFile);

您当然需要catch 这些反射调用可能引发的几个异常。

【讨论】:

  • 您能否详细说明“传入代表参数类型的类对象,而不是类的字符串名称”时的意思。不确定要为参数类型传递什么到 getDeclaredConstructor()?我以为这只是构造函数接受的参数?
  • 正如我回答的最后一部分所示,您可以传入代表参数类型的Class 对象。
  • 哦,我明白了......但是现在我将如何实际传递这些参数,我看到这只是构造构造函数的原型,用于创建构造函数的新 newInstance。这甚至可以工作:DecisionTableBuilder builder =constructor.newInstance(log, graphDir, outputDir);我将问题修改为 EDIT
  • 是的;我在答案中添加了更多内容。
猜你喜欢
  • 2012-11-12
  • 2014-03-28
  • 1970-01-01
  • 2015-10-08
  • 2015-11-21
  • 2014-04-01
  • 2017-01-12
  • 2016-05-09
  • 2011-10-15
相关资源
最近更新 更多