Karena kode Scala dikompilasi menjadi bytecode yang sama dengan kode Java, seluruh pustaka Java dapat digunakan dari Scala tanpa lapisan penghubung apa pun. Topik ini membahas cara memanggil kelas dan pustaka Java langsung dari Scala, cara scala-cli mengompilasi proyek campuran yang berisi berkas .java dan .scala sekaligus, serta konversi koleksi di antara dua ekosistem dengan scala.jdk.CollectionConverters. Perbedaan konvensi panggilan yang perlu dijaga agar kedua sisi tetap kompatibel dibahas pada bagian akhir.
Pustaka Java digunakan langsung dari Scala#
Kelas Java diperlakukan sebagai kelas biasa di Scala. Kelas dari pustaka standar Java seperti java.time.LocalDate atau java.util.ArrayList cukup diimpor dengan import, lalu dibuat dengan new dan metodenya dipanggil seperti pada kelas Scala. Pustaka Java pihak ketiga yang beredar sebagai berkas .jar juga berlaku sama, karena tidak ada perbedaan format bytecode di antara keduanya.
Beberapa konvensi panggilan Java diterjemahkan secara alami. Metode statis (static method) diakses melalui nama kelasnya, sebagaimana KonversiSuhu.fahrenheitKeCelsius(98.6) pada bagian berikutnya. Metode Java selalu dipanggil dengan tanda kurung meskipun tidak memiliki parameter, karena tidak ada aturan Scala yang membolehkan metode Java ditulis tanpa tanda kurung. Nilai kembalian void milik Java dilihat oleh Scala sebagai Unit, sehingga metode yang tidak menghasilkan apa pun tetap dapat dipanggil dari ekspresi Scala.
Proyek campuran dengan scala-cli#
scala-cli dapat mengompilasi berkas .java dan .scala yang berada dalam satu direktori sebagai satu proyek. Caranya adalah memberikan masukan berupa direktori, bukan satu berkas, sehingga kelas Java ikut dikompilasi bersama kode Scala. Karena proyek campuran berikut memuat dua titik masuk, yaitu main milik kelas Java dan @main milik Scala, direktif //> using mainClass interop pada berkas Scala menetapkan program mana yang dijalankan.
// Kelas Java sederhana untuk konversi satuan suhu
public class KonversiSuhu {
// Mengonversi suhu dari Fahrenheit ke Celsius
public static double fahrenheitKeCelsius(double fahrenheit) {
return (fahrenheit - 32.0) * 5.0 / 9.0;
}
// Program kecil agar berkas ini dapat dijalankan sendiri
public static void main(String[] args) {
System.out.printf("98.6 Fahrenheit = %.1f Celsius%n", fahrenheitKeCelsius(98.6));
}
}98.6 Fahrenheit = 37.0 CelsiusKelas Java di atas dapat diuji sendiri dengan perintah java KonversiSuhu.java, sedangkan metode statisnya dipanggil dari sisi Scala pada program campuran berikut.
//> using mainClass interop
// Proyek campuran: memanggil kelas Java dan mengonversi koleksi
import scala.jdk.CollectionConverters.*
import java.time.LocalDate
import java.util.ArrayList
@main def interop(): Unit =
// Kelas Java KonversiSuhu dipanggil langsung dari Scala
val celsius = KonversiSuhu.fahrenheitKeCelsius(98.6)
println(f"98.6 Fahrenheit setara $celsius%.1f Celsius")
// Pustaka Java bawaan dipakai tanpa pembungkus
val tanggal = LocalDate.of(2026, 1, 15)
println(s"Tanggal uji: $tanggal")
// ArrayList Java diisi lalu dilihat dari sisi Scala
val peserta = new ArrayList[String]()
peserta.add("ali")
peserta.add("budi")
val daftarScala = peserta.asScala.toList
println(s"Hasil asScala.toList: $daftarScala")
println(s"Elemen pertama via get: ${peserta.get(0)}")
println(s"Elemen pertama via apply: ${daftarScala(0)}")
// List Scala dikembalikan ke sisi Java
val daftarJava = daftarScala.asJava
println(s"Hasil asJava: $daftarJava")# mengompilasi dan menjalankan seluruh proyek campuran
scala-cli run .98.6 Fahrenheit setara 37.0 Celsius
Tanggal uji: 2026-01-15
Hasil asScala.toList: List(ali, budi)
Elemen pertama via get: ali
Elemen pertama via apply: ali
Hasil asJava: [ali, budi]Baris pertama keluaran berasal sepenuhnya dari kelas Java, yaitu hasil KonversiSuhu.fahrenheitKeCelsius(98.6) yang dicetak sebagai 37.0 dengan format satu angka desimal. Baris kedua menggunakan LocalDate dari pustaka java.time tanpa pembungkus apa pun. Baris-baris sisanya melibatkan koleksi, dan polanya dibahas pada bagian berikut.
Koleksi Java dan konverter#
Koleksi Java seperti ArrayList bersifat mutable, sedangkan koleksi Scala yang lazim bersifat immutable, sehingga keduanya tidak dapat dipertukarkan secara langsung. Jembatannya adalah objek scala.jdk.CollectionConverters yang menyediakan metode perluasan (extension method) asScala dan asJava. Pada ArrayList yang berisi string, peserta.asScala menghasilkan Buffer yang merupakan tampilan (view) di atas koleksi Java aslinya, dan toList menyalinnya menjadi List Scala yang berdiri sendiri.
Sifat tampilan dan salinan ini perlu diperhatikan karena keduanya terlihat sama ketika dicetak.
Pada program di atas, daftarScala = peserta.asScala.toList menghasilkan List(ali, budi) yang sepenuhnya milik sisi Scala. Sebaliknya, daftarScala.asJava membungkus List Scala menjadi objek yang memenuhi antarmuka java.util.List, sehingga metode Java seperti get dapat dipanggil padanya. Ketika dicetak, koleksi Java menampilkan format kurung siku [ali, budi], sedangkan koleksi Scala menampilkan format List(ali, budi), dan perbedaan ini berguna untuk mengenali sisi asal sebuah koleksi.
Perbedaan konvensi antara Java dan Scala#
Di luar koleksi, beberapa perbedaan konvensi muncul secara berulang saat kedua bahasa dipertemukan. Tabel berikut merangkum pasangan yang paling sering ditemui.
| Aspek | Sisi Java | Sisi Scala |
|---|---|---|
| Akses elemen menurut indeks | peserta.get(0) | daftarScala(0) melalui apply |
| Nilai yang tidak ada | null | Option dengan None |
| Metode tanpa nilai kembalian | void | Unit |
| Akses atribut melalui getter | data.getNilai() | properti data.nilai pada kelas Scala |
get dan apply sama-sama mengambil elemen pada indeks tertentu, tetapi get adalah metode khas antarmuka java.util.List, sedangkan apply adalah metode penerapan (application method) yang membuat penulisan daftarScala(0) mungkin. Pada program di atas, kedua cara menghasilkan ali dari data yang sama. Perbedaan penanganan null lebih berisiko, karena kelas Java dapat mengembalikan null tanpa aba-aba.
Konvensi void dan Unit tidak menuntut penyesuaian apa pun karena penerjemahannya otomatis. Perbedaan getter hanya berlaku searah, yaitu atribut kelas Scala dapat diakses seperti properti, sedangkan atribut kelas Java tetap dipanggil dengan getter-nya.
Ringkasan#
- Kelas dan pustaka Java dipanggil dari Scala tanpa lapisan penghubung, dengan metode Java selalu ditulis bertanda kurung dan metode statis diakses melalui nama kelasnya.
- scala-cli mengompilasi proyek campuran
.javadan.scaladalam satu direktori ketika masukannya berupa direktori, yaituscala-cli run .. asScaladanasJavamenghasilkan tampilan yang terhubung ke koleksi asal, sedangkantoListmenyalin isi ke koleksi immutable yang berdiri sendiri.- Konvensi yang perlu dijaga mencakup
getversusapply, penanganannulldenganOption, serta pemetaanvoidkeUnityang berlangsung otomatis.
Referensi#
- Interaction with Java — Scala Documentation — Bab resmi buku Scala 3 tentang menggunakan kelas Java dari Scala.
- Conversions Between Java and Scala Collections — Scala Documentation
— Tabel konversi resmi beserta catatan sifat tampilan pada
asScaladanasJava. - Scala for Java Programmers — Scala Documentation — Tutorial resmi yang membandingkan konvensi kedua bahasa.
- CollectionConverters — Scala Standard Library — Dokumentasi API objek konverter pada pustaka baku 3.x.