Можно ли использовать scala List непосредственно в Java?

Могу ли я использовать scala List в Java, например:

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 List, для использования Java-кода у меня есть два варианта:

  • использовать scala Список непосредственно в java

  • напишите класс-оболочку, который возвращает java.util.List для этих методов.

Я бы предпочел вариант 1, потому что в противном случае мне придется написать класс-оболочку почти для всех моих классов scala.

Но я просто не могу получить scala List, запущенный на Java.

Ответ 1

Маленький метод помощника на стороне 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/

Ответ 2

Как и в случае с Scala 2.10, я не справился с этими трюками.

Но вы можете использовать следующий код:

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

Ответ 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

Вызов Scala из Java не так забавен, как вызов Java из scala. Я думаю, вам будет легче преобразовать список Scala в коллекцию Java. Использование любой из функций Scala List более высокого порядка будет сложным в Java, и без них вы все равно будете иметь коллекцию Java.