Kotlin과 Java 함께 사용하기
타입
코틀린에서 자바 코드를 불러오면 코틀린 타입으로 전환된다.
e.g.) int → Int / Integer → Int! / void → Unit / double[] → DoubleArray! / T[] → Array<T>! / Object → Any
자바의 참조 타입을 코틀린으로 불러오면 타입 이름 뒤에 느낌표가 붙는다. (String! 처럼)
이는 실제 문법은 아니고 IDE에서 Nullable인지 Not-Null인지 알 수 없어서 표시하는 것뿐이다.
String! 타입은 String?이나 String으로 적을 수 있으나,
null이 들어오지 않는다는 확신이 없으면 String?으로 적어주는 것이 안전하다.
자바에서 @NotNull 어노테이션이 붙은 매개변수 타입은 코틀린에서 String으로 인식된다.
키워드 충돌
코틀린에서 키워드인 것이 자바에서 식별자로 쓰일 때가 있다. (코틀린의 in / 자바의 System.in 처럼)
이럴 때는 문제가 되는 식별자를 ` 로 감싸주면 된다.
` 은 특수문자가 들어간 식별자를 지을 때도 사용된다. val `이 변수`: Int = 10
함수형 인터페이스
함수 리터럴 앞에 단일 추상 메서드를 갖는 인터페이스 이름을 적으면 그 인터페이스 타입으로 표현식이 변한다.
// Java
Runnable runnable = () -> System.out.println("run anything!");
// Kotlin
val runnable: Runnable = Runnable { println("run anything!") }
연산자 오버로딩
자바의 메서드 중, 연산자를 오버로딩하는 이름의 메서드가 있으면 코틀린에서 연산자 형태로 접근할 수 있다.
public class JavaClass {
public boolean contains(int any) {
return any < 10;
}
public int get(int any) {
return any * 10;
}
}
fun main(args: Array<String>) {
val java = JavaClass()
println(5 in java) //true
println(java[3]) //30
}
클래스 참조
자바 메서드 중 Class<T> 타입의 인수를 요구하는 경우가 있다.
이때 코틀린 클래스의 인스턴스로부터 Class<T> 타입의 값을 얻어내려면,
인스턴스 뒤나 클래스 이름 뒤어 ::class.java 를 적으면 된다.
자바에서 코틀린의 패키지 레벨 변수, 함수에 접근하기
자바에는 전역변수, 전역함수의 개념이 없다.
코틀린 파일에 선언된 패키지 레벨의 변수, 함수들은 파일명Kt 클래스의 static 멤버로 인식된다.
// File1.kt
val a = 10
fun func1() = println("Hello1")
fun Int.extension() = println(this)
// File2.kt
@file:JvmName("MyKotlin")
fun func2() = println("Hello2")
// Main.java
public class Main {
public static void main(String[] args) {
System.out.println(File1Kt.getA()); //10
File1Kt.func1(); //Hello1
File1Kt.extension(100) //100
MyKotlin.func2(); //Hello2
}
}
자바에서 코틀린의 패키지 레벨 변수는 오로지 Getter, Setter를 통해서만 접근할 수 있다.
@file:JvmName("MyKotlin") 어노테이션은 그 파일에 대한 클래스 이름을 지정할 수 있게 한다.
자바에서 코틀린의 프로퍼티에 접근하기
자바에서 코틀린의 프로퍼티는오로지 Getter, Setter를 통해서만 접근할 수 있다.
// KotlinClass.kt
class KotlinClass {
var num: Int = 0
}
// Main.java
public class Main {
public static void main(String[] args) {
KotlinClass kotlin = new KotlinClass();
kotlin.setNum(10);
System.out.println(kotlin.getNum()); //10
}
}
아래처럼 프로퍼티에 @JvmField 어노테이션을 붙이면 필드 형태로 접근할 수 있다.
@JvmField 어노테이션을 붙이기 위해서는 private이 아니어야 하고, open, override, const 키워드를 붙일 수 없으면, delegated property가 아니어야 한다.
// KotlinClass.kt
class KotlinClass {
@JvmField
var num: Int = 0
}
아래처럼 @JvmName("이름") 어노테이션을 붙이면 원하는 이름으로 Getter, Setter가 만들어진다.
// KotlinClass.kt
class KotlinClass {
var num: Int = 0
@JvmName("name") get
@JvmName("name") set
}
// Main.java
kotlin.name(10);
System.out.println(kotlin.name());
자바에서 코틀린의 Object 객체에 접근하기
// KotlinObject.kt
object KotlinObject {
var num = 55
fun hello() = println("Hello")
}
// Main.java
public class Main {
public static void main(String[] args) {
System.out.println(KotlinObject.INSTANCE.getNum());
KotlinObject.INSTANCE.setNum(0);
KotlinObject.INSTANCE.hello();
}
}
object 키워드로 선언된 객체는 자바에서 일반적인 클래스로 인식되며, INSTANCE라는 static 필드를 자동으로 갖는다.
INSTANCE 필드 없이 객체의 프로퍼티와 멤버함수에 접근하려면, 프로퍼티와 멤버함수에 @JvmStatic 어노테이션을 붙여줘야 한다. @JvmStatic을 붙여주면 Getter, Setter, 메서드가 static으로 생성된다.
자바에서 코틀린의 Companion Object 객체에 접근하기
// KotlinClass.kt
class KotlinClass {
companion object {
var num = 0
fun hello = println("Hello")
}
}
// Main.java
public class Main {
public static void main(String[] args) {
KotlinClass,Companion.setNum(30);
System.out.println(KotlinClass.Companion.getNum());
KotlinClass.Companion.hello();
}
}
동반자 객체가 있는 클래스는 자바에서 Companion이라는 static 필드를 갖는다. 각 멤버에 @JvmStatic 어노테이션을 붙여 static으로 접근하게 할 수 있다.