자바 interop·코틀린 관용구 — 두 언어가 만나는 곳
안드로이드 코드베이스는 코틀린과 자바가 섞여 있는 경우가 많다 — 오래된 자바 코드, 자바로 짠 라이브러리, 그리고 새 코틀린 코드. 코틀린은 자바와 100% 상호운용되지만, 경계에서 주의할 점이 있다. 이 장은 interop 실무와, 자주 쓰는 *코틀린 관용구(Effective Kotlin 요점)*를 모은다 — andkt 언어편의 마무리다. (출처: Kotlin Docs — Java interop / Calling Kotlin from Java / Effective Kotlin.)
코틀린에서 자바 호출 — 플랫폼 타입을 조심
자바 메서드는 null 정보가 없어 코틀린에서 *플랫폼 타입(String!)*으로 보인다([02 널 안전]). 자바가 null을 줄 수 있으면 런타임 NPE 위험이니, 경계에서 명시 타입으로 받아 null 처리한다.
val name: String? = javaUser.getName() // 자바 반환을 String?로 명시 → 강제 null 처리
자바의 getter/setter는 코틀린에서 프로퍼티처럼 보인다 — javaUser.name(getName 호출). 자바 라이브러리에 @Nullable/@NonNull이 달려 있으면 코틀린이 정확한 nullability로 본다.
자바에서 코틀린 호출 — @Jvm 어노테이션
반대로 자바에서 코틀린을 쓸 때 매끄럽게 하려면 어노테이션을 단다.
class Util {
companion object {
@JvmStatic fun parse(s: String) = ... // 자바에서 Util.parse() (없으면 Util.Companion.parse())
}
}
@JvmOverloads // 기본 인자 → 자바용 오버로드 생성
fun greet(name: String, polite: Boolean = true) { }
const val MAX = 100 // 자바에서 상수처럼 (@JvmField도)
@JvmStatic— companion 멤버를 진짜 정적으로(자바 호출 간결).@JvmOverloads— 기본 인자를 자바용 오버로드 메서드로 펼침(자바엔 기본 인자가 없으므로).@JvmField— 프로퍼티를 필드로 노출(getter 우회).@JvmName— 시그니처 충돌 시 자바에서 보일 이름 변경.@Throws— 코틀린엔 checked 예외가 없으니, 자바에throws선언이 필요하면 명시.
SAM 변환 — 함수형 인터페이스를 람다로
자바의 *단일 추상 메서드 인터페이스(SAM)*는 코틀린에서 람다로 넘길 수 있다.
button.setOnClickListener { v -> onClick() } // OnClickListener(SAM)를 람다로
executor.execute { doWork() } // Runnable을 람다로
코틀린 자체 인터페이스를 SAM처럼 쓰려면 fun interface로 선언한다.
자주 쓰는 코틀린 관용구
실무에서 반복되는 Effective Kotlin 식 패턴들:
// 1) 인자 검증 — require/check (IllegalArgument/IllegalState)
fun setAge(age: Int) {
require(age >= 0) { "나이는 음수 불가: $age" } // 아니면 IllegalArgumentException
}
// 2) 리소스 자동 해제 — use (자바 try-with-resources)
file.bufferedReader().use { reader ->
reader.readText() // 블록 끝나면 자동 close (예외 나도)
}
// 3) 안전한 결과 래핑 — runCatching
val result = runCatching { api.load() }
.getOrElse { emptyList() } // 예외 시 기본값
// 4) when/if를 식으로 — 분기마다 값 반환 (망라성)
val label = when (state) { ... }
기타 관용구 — 불변 우선(val·읽기 전용 컬렉션), 명명 인자로 가독성, 데이터는 data class, 상태는 sealed, !! 최소화, 확장 함수로 유틸. 이것들이 코틀린다운(idiomatic) 코드다.
interop 시 흔한 함정
- 코틀린 top-level 함수는 자바에서
파일명Kt.함수()로 보인다(@file:JvmName으로 변경). - 코틀린 기본 인자는 자바에서 안 보인다(
@JvmOverloads필요). - 코틀린
Unit은 자바void,Nothing은 특수 처리.
정리 — 경계를 알면 섞어 쓸 수 있다
코틀린-자바 interop의 핵심 — 자바에서 올 땐 플랫폼 타입(NPE)을 명시 타입으로 방어, 자바로 노출할 땐 @JvmStatic/@JvmOverloads/@JvmField로 매끄럽게, SAM은 람다로. 그리고 require/check·use·runCatching·불변·명명 인자 같은 관용구가 코틀린다운 코드를 만든다. 이제 언어를 갖췄으니, [andarch] 아키텍처와 [andsys] 프레임워크로 넘어간다.
한 줄 요약 — 자바→코틀린: 플랫폼 타입 명시로 NPE 방어, getter는 프로퍼티. 코틀린→자바:
@JvmStatic·@JvmOverloads·@JvmField·@JvmName·@Throws. SAM은 람다(fun interface). 관용구:require/check·use·runCatching·불변·명명 인자.
(출처: Kotlin — Java Interop / Calling Kotlin from Java / Effective Kotlin / Android Kotlin-Java interop guide.)