Java Interoperability

Calling Scala from Java:

object members are accessible as static forwarders (MyObj.method()), or via MyObj$.MODULE$.

Use @throws, @varargs, @BeanProperty, @static, @targetName for Java-friendly APIs.

Avoid exposing Scala-specific types (implicits, default params) in Java-facing APIs.

Null handling: wrap Java returns with Option(...); with explicit nulls Java types become T | Null.

import java.time.{LocalDate, Duration}
import java.util.{ArrayList, HashMap}
import scala.jdk.CollectionConverters.*
import scala.jdk.OptionConverters.*
import scala.jdk.FunctionConverters.*
import scala.jdk.FutureConverters.*

val today = LocalDate.now().plusDays(3)
val jlist = ArrayList[String](); jlist.add("a")
jlist.asScala.toList
List(1, 2).asJava
java.util.Optional.of(1).toScala          // Some(1)
Some(1).toJava
javaCompletableFuture.asScala             // Future

// Lambdas → Java functional interfaces (SAM conversion)
val r: Runnable = () => println("run")
jlist.forEach(s => println(s))