【问题标题】:How to run .java file with Variable Name如何使用变量名运行 .java 文件
【发布时间】:2015-06-20 02:24:17
【问题描述】:

我正在尝试基于 Pebble Smartwatch 操作系统制作一个程序。我有一个名为PebbleOS_Faces.txt 的文本文件,其中包含我将在手表上使用的不同表盘的所有名称。

我使用PrintWriter 将内容转换为.java 文件,然后使用从this post 获得的代码对其进行编译。它被编译到所有其他类旁边的 build/classes/pebbleos 文件夹中(我使用的是 Mac 版 Netbeans,以防有所不同)。我已经确认这一切正常。

剩下的就是让我从程序内部实际运行课程。问题是,根据PebbleOS_Faces.txt 文件中的表盘名称,每个类都有不同的名称。如何创建具有变量名的类的实例?

【问题讨论】:

标签: java class


【解决方案1】:

我从未尝试过动态生成/编译的类,但是...

尝试使用 Class.forName("com.example.YourClassName") 获取对该类的引用:

http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#forName(java.lang.String)

然后使用 Class.newInstance() 创建类的实例:

http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#newInstance()

为此,com.example.YourClassName 必须对您的类加载器可见。

例如:

Class clazz = Class.forName("com.example.YourClassName");
Object instance = clazz.newInstance();

newInstance() 调用仅在您的类具有无参数构造函数时才有效。

如果 YourClassName 类的构造函数需要参数,您必须使用稍微不同的技术来调用特定构造函数并将值传递给它。例如,如果你有这样的构造函数:

YourClassName(Integer someInt, String someString)

然后您可以通过该构造函数实例化 YourClassName:

Class clazz = Class.forName("com.example.YourClassName");
Constructor constructor = clazz.getConstructor(Integer.class, String.class);
Object instance = constructor.newInstance(anInteger, "aString");

如果 YourClassName 的每个实例都实现相同的 interface 或扩展相同的基类,以便您可以将 newInstance() 的返回值强制转换为该接口或基类,这可能会有所帮助。然后您就可以在实例上调用接口或基类的方法。否则,您在 Object 上调用有用方法的唯一方法是 use reflection

【讨论】:

  • 遵循您的建议后,我收到以下错误:线程“main”中的异常 java.lang.ClassNotFoundException: PebbleOS_Default,其中 Default 是表盘的名称。该类可能在错误的目录中吗?
  • 可能。 PebbleOS_Default 类的包名是什么?
  • 包名是pebbleos,和其余文件的包名一样。
  • 啊,在这种情况下,我会确保类文件位于 build/classes/pebbleos/PebbleOS_Default.class,并仔细检查 /path/to/build/classes 是否在类路径。这看起来是一个有趣的检查列表:myarch.com/classnotfound(尽管那里的许多建议似乎都是针对 Web 应用程序的,可能对您没有帮助)
  • 您也可以在这里使用 prunge 的答案 stackoverflow.com/questions/7590495/… 在运行时打印您的类路径,并使用它来确认构建/类在类路径上。
【解决方案2】:

您需要使用 反射。您可以使用Class.forName(String) 按名称获取Class 对象。您可以使用Class.getConstructors()[0].newInstance(<insert constructor arguments here>)* 调用构造函数。确保所有类都继承一个公共超类,以便您可以执行以下操作:

WatchFace face = Class.forName(watchFaceName).getConstructors()[0].newInstance();

*这是假设只有一个构造函数

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-01
    • 1970-01-01
    • 2010-10-07
    • 2016-11-24
    • 1970-01-01
    • 1970-01-01
    • 2015-02-14
    相关资源
    最近更新 更多