gpt4 book ai didi

java - 从 Java 调用多态 Scala 方法

转载 作者:行者123 更新时间:2023-12-03 20:18:55 25 4
gpt4 key购买 nike

我正在编写一个 API,我希望它可以在 Scala 和 Java 中使用。我在 Scala 类中定义了一个多态方法,但我无法从 Java 调用它。

根据此互操作性FAQ在 scala-lang.org,使用使用高级语言特性的 Scala 类“可能很棘手”但它并没有说这是不可能的。由于没有记录 Scala 的高级功能如何转换为 Java,因此建议反汇编类文件以试验其工作方式。

示例代码

class Polymorphic {
def polyMethod[T](implicit om: Manifest[T]) = {
println(om.erasure.getName)
om.erasure.newInstance
}
}

object Polymorphic {
def main(args: Array[String]) {
val objOfT = (new Polymorphic).polyMethod[String]
}
}

这在 scala 中工作正常,打印“java.lang.String

我在生成的类文件上运行 javap -c 并获得了以下 polyMethod list :

public java.lang.Object polyMethod(scala.reflect.Manifest);
Code:
0: getstatic #20; //Field scala/Predef$.MODULE$:Lscala/Predef$;
3: aload_1
4: invokeinterface #27, 1; //InterfaceMethod scala/reflect/ClassManifest.erasure:()Ljava/lang/Class;
9: invokevirtual #33; //Method java/lang/Class.getName:()Ljava/lang/String;
12: invokevirtual #37; //Method scala/Predef$.println:(Ljava/lang/Object;)V
15: aload_1
16: invokeinterface #27, 1; //InterfaceMethod scala/reflect/ClassManifest.erasure:()Ljava/lang/Class;
21: invokevirtual #41; //Method java/lang/Class.newInstance:()Ljava/lang/Object;
24: areturn

3个主要问题:

  1. 该方法的返回类型是多态的
  2. Manifest 参数在 Java 中不是隐含的
  3. 我实际上无法传递类型参数。

我尝试使用的真实项目代码在这里: https://github.com/ConnorDoyle/EnMAS/blob/master/clientServerPrototype/src/org/enmas/pomdp/State.scala

我的最终目标是一个完全通用但类型安全的数据字典。它在 Scala 中运行良好,但我真的希望也能从 Java API 调用此方法。我的设计动机是在客户端代码中保留反射、显式转换和空检查。

编辑:2011 年 11 月 18 日 回应下方@kassens 的评论

polyMethod 的定义更改为以下内容:

def polyMethod[T](implicit om: Manifest[T]): T = {
println(om.erasure.getName)
om.erasure.newInstance.asInstanceOf[T]
}

当我用 javap 检查类文件时,给出完全相同的字节码。

最佳答案

有几个问题在起作用:

  1. Scala 中的统一泛型。 T 在 Scala 中是无界的(这意味着它可以用原始类型实例化),这使得 Scala 编译器保守地将它删除为 Object。如果您将 Scala 代码更改为

    def polyMethod[T <: AnyRef](implicit om: Manifest[T]) = {
    println(om.erasure.getName)
    om.erasure.newInstance.asInstanceOf[T]
    }

    它将返回 T。请注意 newInstance 的显式转换,因为 Scala 库方法不会返回正确的泛型类型。

  2. 使用 list 。这会添加另一层泛型,您需要对齐它们才能使调用通过。正如 didierd 所建议的那样,最好在 Scala 中使用一个重载来代替 java.lang.Class

所以我的建议是将其添加到您的 Scala 代码中:

  def polyMethod[T <: AnyRef](cls: Class[T]): T = 
polyMethod(Manifest.classType(cls))

然后从 Java 中这样调用它:

void test(Polymorphic p) { 
JavaScalaCall c = p.polyMethod(this.getClass());
}

作为旁注,字节码总是被删除。如果您想查看类文件中的一般信息,请使用例如 jclasslib 查找 Signature 属性。 .

关于java - 从 Java 调用多态 Scala 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8171770/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com