【问题标题】:Scala object struggles with Java Class.newInstance()Scala 对象与 Java Class.newInstance() 的斗争
【发布时间】:2012-03-29 15:22:04
【问题描述】:

更新:

我已经在一定程度上解决了这个问题。以防万一有人遇到同样的问题,这里是最简单的解决方案:查看 MTApplcation 源代码,我发现 initialize() 方法可以重载,采用 String 参数作为要实例化的类的名称。因此,如果我创建一个单独的类来扩展 MTApplication 并在那里传递它的名称,那么一切都会正常工作。

更新结束

我在尝试使用 java 库(MT4j,基于 Processing)时遇到了 Scala 的情况。库想要实例化应用程序的主类(调用者类):

  Class<?> c = Thread.currentThread().getContextClassLoader().loadClass(name);
  applet = (PApplet) c.newInstance();

以便以后在它的作品中引用它。

但是,它失败了,因为,我猜,主 Scala 类不是一个类,而是一个对象,并且由于库结构,需要调用主库类 MTApplication 的静态方法 initialize()。在 Java 中,静态字段位于类中,但在 Scala 中 - 位于对象中。所以不可能实例化一个对象并且库失败。与 MT4j 相比,Processing 本身在启动时不调用静态方法并成功通过该阶段。

如果我只是创建一个伴生类,一切正常,除了伴生类没有初始化其字段,因为在伴生对象中调用了静态 initialize() 方法,类实例就死了,库变成了无法使用。

至少我是这么理解这个问题的。

我收到此错误:

Exception in thread "main" java.lang.RuntimeException: java.lang.IllegalAccessException: Class processing.core.PApplet can not access a member of class main.Main$ with modifiers "private"
    at processing.core.PApplet.runSketch(PApplet.java:9103)
    at processing.core.PApplet.main(PApplet.java:9292)
    at org.mt4j.MTApplication.initialize(MTApplication.java:311)
    at org.mt4j.MTApplication.initialize(MTApplication.java:263)
    at org.mt4j.MTApplication.initialize(MTApplication.java:254)
    at main.Main$.main(Main.scala:26)
    at main.Main.main(Main.scala)

我也很难解释,因为我不完全理解这里发生了什么。但是任何拥有这些库的人都可以在几分钟内重现这种情况,尝试启动主类。

应该实现抽象的startUp() 方法来启动应用程序,让一切看起来更加悲伤。它初始化对象,但库试图使用的是伴随类的一个实例,它没有被初始化,因为在 Scala 中该方法属于该对象。

我的代码:

object Main extends MTApplication {

    def main(args: Array[String]) {
        MTApplication.initialize()
        new Main().startUp()
    }

    //this method is abstarct so it MUST be implemented,
    override def startUp(){ 
    }

}

class Main extends MTApplication {

    override def startUp(){
       //startup here
    }
}

如果我的解释含糊不清,我很抱歉,我只是没有完全理解。可能要理解使用处理源代码而不是预先链接的“core.jar”来重复使用 MT4j 库的实验更容易,以查看内部发生了什么。有人对这里的任何解决方法有想法吗?

【问题讨论】:

    标签: scala object static-methods


    【解决方案1】:

    问题解决了。这是解决方案:

    object Main {
    
        var current: MainC = _
    
        def main(args: Array[String]) {
            MTApplication.initialize("org.mttablescreen.main.MainC")
        }
    
    }
    
    class MainC extends MTApplication {
    
        //cons
        Main.current = this
    
        //cons ends
    
        override def startUp(){
            prepare
        }
    
        def prepare () {...}
    }
    

    【讨论】:

    • 我有兴趣,请给出解决方案
    猜你喜欢
    • 2022-01-08
    • 2020-09-18
    • 2018-05-23
    • 2013-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-24
    相关资源
    最近更新 更多