1

可能重复:
编译包含 java 和 scala 代码的文件

我知道 Scala 可以轻松使用 Java 类。但是,是否可以在 scala 文件中包含 Java 源代码并以任何方式使用 scalac 进行编译?

或者,是否可以在源代码中包含 javac 编译的字节码作为字节数组,并从中导入(哎呀,是的)?

这是家庭作业,所以,不,我不能有单独的文件,它必须用 编译scalac file.scala,没有额外的参数。澄清一下,这是我老师的硬性要求

4

3 回答 3

3

如果你想在 Scala 代码中编写一个字面量字节数组,很容易从它转到一个普通的 Java 类,只需调用Classloader.defineClass. 这意味着您需要创建自己的子类ClassLoader来公开此方法的重载之一。这在 Scala 中都是可行的,没有太多麻烦。

如果你仔细准备,你甚至可以通过让你的 class-from-bytearray 实现你在 Scala 中定义的接口来获得类型安全。我不知道这方面的确切细节,但我记得 Java 类可以继承/实现 Scala 中定义的某些东西。如果做不到这一点,您当然可以进行反思。

于 2012-11-25T19:51:59.520 回答
3

我只是写了一个简单的例子

说你有一个像这样的java类

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("hello world");
    }
}

然后你写一些scala代码把它变成一个字节数组

import java.io.{FileInputStream, FileOutputStream}
import collection.mutable.ArrayBuffer

val in = new FileInputStream("HelloWorld.class")
val out = new FileOutputStream("HelloWorldBytes.scala")

Console.withOut(out) {
  var data = in.read()
  print("val helloWorldBytes = Array[Byte](")
  print(if(data < 128) data else data - 256)
  data = in.read()
  while(data >= 0) {
    print(", ")
    print(if(data < 128) data else data - 256)
    data = in.read()
  }
  println(")")
}


in.close()
out.close()

然后你可以像这样使用它

val helloWorldBytes = Array[Byte](...)

object Loader extends ClassLoader {
  override
  def findClass(name: String): Class[_] =
    if(name == "HelloWorld") defineClass(name, helloWorldBytes, 0, helloWorldBytes.size)
    else super.findClass(name)
}

val helloWorld = Loader.loadClass("HelloWorld")
helloWorld.getDeclaredMethod("main", classOf[Array[String]]).invoke(null,null)
于 2012-11-25T21:02:05.880 回答
1

可以使用BCEL并在 Scala 中指定一个 Javac 派生的指令列表,但我真的无法想象这在任何方面是如何实用的。做你想做的最简单的方法是使用(比如说)Maven scala 插件将 Java 和 Scala 文件一起编译。

于 2012-11-25T19:34:21.543 回答