我可以直接在Java中使用scala List吗?

Vis*_*hao 14 java scala-java-interop scala-collections

我可以在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

它似乎没有编译.找不到List $ .apply方法.

当我改变它

List xs = Dir.ls()
Run Code Online (Sandbox Code Playgroud)

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

"内部编译器错误:java.lang.ClassCastException:org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding无法强制转换为org.eclipse.jdt.internal中的org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding. compiler.lookup.BinaryTypeBinding.initializeTypeVariable(BinaryTypeBinding.java:927)"

我不知道这是什么意思.


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

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

  1. 直接在java中使用scala List

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

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

但我只是无法让scala List在Java中运行.

Seb*_*ber 18

Scala 2.10开始,我没有成功使用上述技巧.

但您可以使用以下代码:

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


Lan*_*dei 13

一个小的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

[更新]

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


Jan*_*anx 6

这种语法的问题:

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
Run Code Online (Sandbox Code Playgroud)

从Java调用Scala并不像从Scala调用Java那么有趣.我认为您可以更轻松地将Scala列表转换为Java Collection.在Java中使用任何Scala List更高阶函数都很困难,如果没有这些函数,你几乎就会拥有一个Java Collection.