2012-10-09 73 views
1

TL; DR:當我使用第一個變體時,REPL運行對象正常,但是當我用package test替換import test._時,即使成功編譯的代碼也無法運行爲了編譯。Scala無法運行編譯的類,但直接運行它

我用Scala編寫一個簡單的Hello World應用程序:

import test._ 
object TestApp { 
    def main (args: Array[String]) { 
    val p = new HelloWorldPrinter 
    p.output() 
    } 
} 

的HelloWorldPrinter.output()方法只是println("Hello World");

當我與scala TestApp.scala它的工作原理和輸出的Hello World運行應用程序,然而,當我運行fsc或scalac進行編譯時,它會生成一個包含相同包名稱「test」的子文件夾,並將TestApp.class放在那裏。然後,如果我跑scala test/TestApp它不工作,並拋出這個錯誤:

Exception in thread "main" java.lang.RuntimeException: Cannot figure out how to run target: test/TestApp 
    at scala.sys.package$.error(package.scala:27) 
    at scala.tools.nsc.GenericRunnerCommand.scala$tools$nsc$GenericRunnerCommand$$guessHowToRun(GenericRunnerCommand.scala:38) 
    at scala.tools.nsc.GenericRunnerCommand$$anonfun$2.apply(GenericRunnerCommand.scala:48) 
    at scala.tools.nsc.GenericRunnerCommand$$anonfun$2.apply(GenericRunnerCommand.scala:48) 
    at scala.Option.getOrElse(Option.scala:108) 
    at scala.tools.nsc.GenericRunnerCommand.<init>(GenericRunnerCommand.scala:48) 
    at scala.tools.nsc.GenericRunnerCommand.<init>(GenericRunnerCommand.scala:17) 
    at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:33) 
    at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:89) 
    at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala) 

但是,如果我cd爲「測試」,以從那裏運行已編譯的類,我得到一個完全不同的錯誤:

Exception in thread "main" java.lang.NoClassDefFoundError: TestApp (wrong name: test/TestApp) 
    at java.lang.ClassLoader.defineClass1(Native Method) 
    at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631) 
    at java.lang.ClassLoader.defineClass(ClassLoader.java:615) 
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141) 
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:283) 
    at java.net.URLClassLoader.access$000(URLClassLoader.java:58) 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:197) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190) 
    at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.scala$tools$nsc$util$ScalaClassLoader$$super$findClass(ScalaClassLoader.scala:88) 
    at scala.tools.nsc.util.ScalaClassLoader$class.findClass(ScalaClassLoader.scala:44) 
    at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.findClass(ScalaClassLoader.scala:88) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306) 
    at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.scala$tools$nsc$util$ScalaClassLoader$$super$loadClass(ScalaClassLoader.scala:88) 
    at scala.tools.nsc.util.ScalaClassLoader$class.loadClass(ScalaClassLoader.scala:50) 
    at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.loadClass(ScalaClassLoader.scala:88) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247) 
    at java.lang.Class.forName0(Native Method) 
    at java.lang.Class.forName(Class.java:247) 
    at scala.tools.nsc.util.ScalaClassLoader$$anonfun$tryClass$1.apply(ScalaClassLoader.scala:37) 
    at scala.tools.nsc.util.ScalaClassLoader$$anonfun$tryClass$1.apply(ScalaClassLoader.scala:37) 
    at scala.util.control.Exception$Catch$$anonfun$opt$1.apply(Exception.scala:104) 
    at scala.util.control.Exception$Catch$$anonfun$opt$1.apply(Exception.scala:104) 
    at scala.util.control.Exception$Catch.apply(Exception.scala:88) 
    at scala.util.control.Exception$Catch.opt(Exception.scala:104) 
    at scala.tools.nsc.util.ScalaClassLoader$class.tryClass(ScalaClassLoader.scala:36) 
    at scala.tools.nsc.util.ScalaClassLoader$class.tryToLoadClass(ScalaClassLoader.scala:31) 
    at scala.tools.nsc.util.ScalaClassLoader$URLClassLoader.tryToLoadClass(ScalaClassLoader.scala:88) 
    at scala.tools.nsc.util.ScalaClassLoader$.classExists(ScalaClassLoader.scala:120) 
    at scala.tools.nsc.GenericRunnerCommand.scala$tools$nsc$GenericRunnerCommand$$guessHowToRun(GenericRunnerCommand.scala:34) 
    at scala.tools.nsc.GenericRunnerCommand$$anonfun$2.apply(GenericRunnerCommand.scala:48) 
    at scala.tools.nsc.GenericRunnerCommand$$anonfun$2.apply(GenericRunnerCommand.scala:48) 
    at scala.Option.getOrElse(Option.scala:108) 
    at scala.tools.nsc.GenericRunnerCommand.<init>(GenericRunnerCommand.scala:48) 
    at scala.tools.nsc.GenericRunnerCommand.<init>(GenericRunnerCommand.scala:17) 
    at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:33) 
    at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:89) 
    at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala) 

什麼給?

編輯:

這是我TestApp.scala對象:https://gist.github.com/3863344

這是我Printers.scala類:https://gist.github.com/3863348

與FSC編譯後運行scala test/TestApp給我的第一個錯誤。輸入test子文件夾並運行scala TestApp給我第二個錯誤。在主文件夾中運行scala TestApp.scala給了我這樣的:

TestApp.scala:1: error: illegal start of definition 
package test 
^ 
one error found 

編輯2:我剛剛發現REPL不能運行包聲明代碼,讓我明白爲什麼上面的錯誤發生。但是,我仍然無法運行我編譯的代碼。

+3

你確定你不會錯過某處的'package test' - 只有這樣你才能在測試文件夾中結束這個類,你應該可以使用'scala test.TestApp'從外部測試中執行它' –

+0

有趣的事實:如果我將「import test._」替換爲「包測試」,我不能再運行該腳本,但我可以編譯它,然後成功運行它,而無需進入測試構建子文件夾。無論我做什麼,看起來我都無法吃掉它 - 我可以在使用導入時運行腳本,或者在使用包時運行編譯後的類(最終在測試文件夾外部結束)。 – Swader

+0

@BijuKunjummen有正確的答案。 – pedrofurla

回答

1

嘗試從主文件夾運行編譯代碼scala test.TestApp(在運行編譯類scala接受類名作爲其參數而不是文件名)。

Scala(就像java一樣)有一個搜索類的位置列表 - 稱爲類路徑。默認情況下,該位置設置爲當前目錄。然後對於給定的類packageX.packageY.ClassName它搜索相應的.class文件packageX/packageY/ClassName.class。因此,如果運行scala test.TestApp而沒有顯式的類路徑,它會找到編譯的文件test/TestApp.class並運行它。

+0

這可行,但爲什麼?如果我從班級所在的文件夾之外運行它,它如何知道班級在哪裏? – Swader

+0

我現在明白了。當我編譯時,我得到按文件夾排列的字節碼類,每個點代表一個新的層次。當我說運行test.TestApp時,它隱式知道它在名爲test的子文件夾中。如果我將它從測試文件夾中刪除,然後運行'scala TestApp'或'scala test.TestApp'都不會工作,因爲具有包的類要求它位於文件夾樹中,路徑與包名相同, ?在這方面,不可能在一個包外運行屬於一個包的類? – Swader

+1

@Swader是的,沒錯。如果您將該類移動到包文件夾外部,scala或java都不能加載並運行它。 –