File-level Names and SAM Conversions

@file:JvmName

Example

Top-level functions in Strings.kt would live in class StringsKt. With @file:JvmName Java callers write StringUtils.slugify(...). Even main moves to that class.

@file:JvmName("StringUtils")

fun slugify(title: String): String =
    title.lowercase().replace(Regex("[^a-z0-9]+"), "-").trim('-')

fun main() {
    println(slugify("Kotlin Coroutines: A Beginner's Guide!"))
    println("Compiled into class: ${object {}.javaClass.enclosingClass.simpleName}")
}

Output

kotlin-coroutines-a-beginner-s-guide
Compiled into class: StringUtils

SAM Conversions

Example

A Java interface with a Single Abstract Method (Runnable, Comparator, Callable, OnClickListener) accepts a Kotlin lambda. For your own Kotlin interfaces, declare them as fun interface to get the same.

import java.util.concurrent.Callable
import java.util.concurrent.Executors

fun interface PriceRule {
    fun apply(price: Int): Int
}

fun main() {
    val byLength = Comparator<String> { a, b -> a.length - b.length }
    println(listOf("banana", "fig", "apple").sortedWith(byLength))

    val pool = Executors.newSingleThreadExecutor()
    val future = pool.submit(Callable { "computed in a Java executor" })
    println(future.get())
    pool.shutdown()

    val festiveDiscount = PriceRule { it * 90 / 100 }
    println("After rule: ${festiveDiscount.apply(1000)}")
}

Output

[fig, apple, banana]
computed in a Java executor
After rule: 900