【问题标题】:Can I use scala List directly in Java?我可以直接在 Java 中使用 scala List 吗?
【发布时间】:2011-05-30 07:40:35
【问题描述】:

我可以在 Java 中使用 scala List,例如:

import scala.collection.immutable.List;
class HelloScalaList {
    public static void main (String[] args) {
        List xs = List(1, 2, 3);
        System.out.println(xs);
    }
}

它似乎无法编译。找不到 List$.apply 方法。

当我把它改成

List xs = Dir.ls()

其中 Dir 是我的 scala 类,而 ls() 返回一个 scala 列表,编译器抱怨

“内部编译器错误:java.lang.ClassCastException:org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding 不能转换为 org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.initializeTypeVariable(BinaryTypeBinding.java:927)"

我不知道这是什么意思。


我想在 scala 中编写一些库,但也希望在 Java 中使用它。

在我的 scala 类中有返回 scala 列表的方法,对于使用它们的 java 代码,我有两个选择:

  1. 直接在java中使用scala List

  2. 编写一个包装类,为这些方法返回 java.util.List。

我更喜欢选项 1,否则我将不得不为我几乎所有的 scala 类编写一个包装类。

但我无法让 scala List 在 Java 中运行。

【问题讨论】:

    标签: java scala-collections scala-java-interop


    【解决方案1】:

    截至 Scala 2.10,我没有成功使用上述技巧。

    但是你可以使用下面的代码:

      public static <T> scala.collection.immutable.List<T> scalaList(List<T> javaList) {
        return scala.collection.JavaConversions.asScalaIterable(javaList).toList();
      }
    

    【讨论】:

      【解决方案2】:

      一个小的 java 端辅助方法可以解决问题:

      import scala.collection.immutable.List;
      import scala.collection.immutable.List$;
      import scala.collection.immutable.$colon$colon;
      
      public class HelloScalaList {
      
          public static void main (String[] args) {
              List xs = list(1,2,3);
              System.out.println(xs);
          }
      
          public static <T> List<T> list(T ... ts) {
              List<T> result = List$.MODULE$.empty();
              for(int i = ts.length; i > 0; i--) {
                  result = new $colon$colon(ts[i - 1], result);
              }
              return result;
          }
      }
      

      [更新]

      由于这个问题,我开始了一个名为“Scava”的小项目,以支持从 Java 到 Scala 的调用:http://code.google.com/p/scava-org/

      【讨论】:

      • 感谢您的努力,但正如 Janx 所指出的,将 Scala 列表转换为 Java 列表有什么好处?
      • @Luigi Plinge:linky 被杀了,因为它没有我想象的那么有用,里面有一些危险的东西,而且与 Scala 2.9 的集成变得更好。
      • 在Scala 2.12中测试,我不能不直接导入$colon$colon,而是需要import scala.collection.immutable.*;
      【解决方案3】:

      这个语法的问题:

      List xs = List(1, 2, 3);

      是 Scala,而不是 Java。当你在 Scala 中实例化一个对象时,语法糖会调用类的伴生对象的 apply() 方法。您必须在 Java 中手动执行此操作。

      而且您实际上并没有创建 scala.collection.immutable.List(这是抽象的):

      scala> val list = List(1,2,3)                      
      list: List[Int] = List(1, 2, 3)
      scala> list.getClass                               
      res12: java.lang.Class[_] = class scala.collection.immutable.$colon$colon
      

      从 Java 调用 Scala 不如从 Scala 调用 Java 有趣。我认为您可以更轻松地将 Scala 列表转换为 Java 集合。在 Java 中使用任何 Scala List 高阶函数都会很困难,如果没有这些函数,无论如何你几乎都有一个 Java 集合。

      【讨论】: