Kotlin

Kotlin과 Java 함께 사용하기

팅리엔 2022. 10. 8. 02:33

타입

코틀린에서 자바 코드를 불러오면 코틀린 타입으로 전환된다.

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으로 접근하게 할 수 있다.