Как интегрировать Scala-код с Java?
Интеграция Scala с Java — одно из сильных преимуществ экосистемы Scala. Scala полностью компилируется в байт-код JVM, а значит, может использовать существующие Java-библиотеки и классы без обёрток или адаптеров. Также Java может вызывать Scala-код, если соблюдать определённые соглашения.
Использование Java-кода в Scala
Scala может напрямую импортировать и использовать Java-классы, пакеты, интерфейсы и методы, как если бы они были написаны на Scala.
Примеры:
Импорт стандартной библиотеки Java:
import java.util.Date
val now = new Date()
println(now)
Использование сторонних Java-библиотек:
import org.apache.commons.lang3.StringUtils
val result = StringUtils.capitalize("scala")
Вызов методов Java-класса:
// Java class
public class Calculator {
public int add(int a, int b) {
return a + b;
}
}
// Scala usage
val calc = new Calculator()
val sum = calc.add(3, 5)
Scala автоматически адаптирует вызов методов, конструкций getX()/setX() и даже принимает boolean как if (condition).
Использование Scala-кода в Java
Для вызова Scala-классов из Java нужно учитывать, что:
-
Scala использует функции как объекты (Function1, Function2, и т.д.)
-
Методы в Scala по умолчанию являются public, но компилируются в методы со специфической сигнатурой
-
Scala-объекты (object) компилируются в final class с суффиксом $ и статическим полем MODULE$
Примеры:
Scala-код:
package demo
object Utils {
def greet(name: String): String = s"Hello, $name"
}
class MathOps {
def square(x: Int): Int = x \* x
}
Java-код:
import demo.MathOps;
import demo.Utils;
public class App {
public static void main(String\[\] args) {
MathOps ops = new MathOps();
System.out.println(ops.square(5));
// доступ к object'у
System.out.println(Utils$.MODULE$.greet("Java"));
}
}
Альтернативно можно добавить аннотацию @scala.annotation.meta.field или использовать Java-friendly API.
Советы по Java→Scala интеграции
- Scala автоматически распознаёт геттеры/сеттеры Java в виде полей:
public class User {
private String name;
public String getName() { return name; }
public void setName(String n) { name = n; }
}
val user = new User()
user.name = "John"
println(user.name)
- Java Optional преобразуется в Scala Option через .asScala из scala.jdk.javaapi.OptionConverters:
import scala.jdk.OptionConverters._
val maybeName: Option\[String\] = someJavaOptional.asScala
Советы по Scala→Java интеграции
- Используй @BeanProperty для генерации Java-геттеров/сеттеров:
import scala.beans.BeanProperty
class Person {
@BeanProperty var name: String = _
}
Java:
Person p = new Person();
p.setName("John");
System.out.println(p.getName());
-
Используй @SerialVersionUID, если ты сериализуешь классы в Java.
-
Для Java-кода, использующего Scala-коллекции, используй преобразования:
import scala.jdk.CollectionConverters._
val list: java.util.List\[String\] = List("a", "b", "c").asJava
Совместимость коллекций
Между java.util.* и scala.collection.* есть автоматические конвертации:
import scala.jdk.CollectionConverters._
val javaList = new java.util.ArrayList\[String\]()
javaList.add("hello")
val scalaList = javaList.asScala.toList
Также работает и наоборот: scalaList.asJava
Аннотации и дополнительные фичи
- @throws(classOf[IOException]) позволяет задать проверяемые исключения, чтобы Java-код знал об этом:
@throws(classOf\[IOException\])
def risky(): Unit = throw new IOException("oops")
- Scala-объекты становятся Singleton в Java, доступные через MODULE$:
MyScalaObject$.MODULE$.method();
Если хочется удобства — можно вручную добавить статическую обёртку в Scala:
object MyUtil {
def add(a: Int, b: Int): Int = a + b
@JvmStatic def addStatic(a: Int, b: Int): Int = add(a, b)
}
Java:
MyUtil.addStatic(3, 4);
Совместимость в sbt
Указание зависимостей на Java:
libraryDependencies += "com.google.guava" % "guava" % "33.0.0-jre"
Поддержка Java 8, 11 и выше указывается через:
javacOptions ++= Seq("--release", "11")
Если используются Java-классы, они должны быть в src/main/java.
Интеграция Scala с Java — двусторонняя и гибкая. Scala понимает Java практически «из коробки», а для Java можно упростить вызовы Scala через аннотации (@BeanProperty, @JvmStatic) и внимание к компиляции объектов (object).