코틀린과 자바

3 minute read

안드로이드 개발 공부를 늦게 시작하여 코틀린으로 했지만, 코틀린 이전의 코드들은 전부 자바 코드여서 자바도 어느 정도 이해를 하고 있어야 한다. 비슷한 두 언어 자바와 코틀린의 공통점과 차이점을 몇가지 정리해보려 한다.

공통점

JVM

JVM(Java Virtual Machine)은 자바를 구동하는 가상 머신이다. 자바와 코틀린 모두 컴파일러가 JVM에서 구동되는 자바 바이트코드로 변환하여 사용된다(코틀린 네이티브를 사용하면 네이티브로 컴파일해 JVM 없이 구동할 수도 있다).

picture 9
코틀린 코드
picture 10
바이트코드
picture 11
디컴파일된 자바 코드

코틀린은 자바 바이트코드로 변환되기 때문에, 자바에 없는 함수를 바이트코드로 변환 후 자바로 디컴파일해서 보면 어떤 식으로 동작하는지 파악할 수 있다.

자바 라이브러리 사용

공통점이라기보단 코틀린과 자바가 100% 호환되기 때문에 가능한 코틀린의 장점이다. 안드로이드 개발을 하다 보면 많은 라이브러리들이 자바로 짜여져 있는데, 코틀린으로 개발하는 안드로이드 앱에서 그러한 라이브러리들이 사용 가능하다. 심지어 한 프로젝트 내에 코틀린과 자바 둘 다 사용할 수도 있다.

picture 12
코틀린 코드에서 Glide 라이브러리를 사용
picture 13
Glide 자바 코드의 일부

차이점

Top-Level Declaration

자바에서는 모든 함수나 변수가 클래스 내에 정의돼있어야 한다. 코틀린에서는 클래스 밖에, 스코프 없이 함수나 변수를 정의할 수 있으며 이를 top-level declaration이라고 부른다.

public class SampleProject {
    public static void main(String[] args) {
        System.out.println("Hello world!")
    }
}

자바 Hello World

fun main() {
    println("Hello world!")
}

코틀린 Hello World

간단한 Hello world 코드를 놓고 보면, 자바는 메인 함수를 클래스 내부에 정의해야하지만 코틀린은 메인 함수를 top-level에 선언할 수 있다.

package com.example.sampleapp.util

import android.graphics.Bitmap
import java.io.ByteArrayOutputStream
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken

fun bitmapToByteArray(bitmap: Bitmap) : ByteArray {
    val outputStream = ByteArrayOutputStream()
    bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
    return outputStream.toByteArray()
}

fun stringToList(value: String): List<Int> {
    val listType = object : TypeToken<List<Int>>() {}.type
    val gson = Gson()
    return gson.fromJson(value, listType)
}

Utils.kt

어디서나 쓰일 수 있는 간단한 함수를 정의하고 싶다면, 자바에서는 클래스 내에 정의해야 하지만 코틀린에서는 파일 하나를 두고 top-level에 선언할 수 있다.

Visibility Modifiers vs Access Modifiers

public, private, protected 등 자바에서는 access modifiers라고 불리던 것들과 비슷한 것들이 코틀린에서 visibility modifiers라고 불린다. 변수 앞에 붙는 이 modifier들은 어디에서까지 접근이 가능한 지를 설정할 수 있다.

Modifier 접근 범위
public 어디서나
default 같은 패키지 내

자바 클래스

Modifier 접근 범위
public 모든 클래스
private 선언된 클래스 내
default 같은 패키지 내
protected 같은 패키지 내, 서브 클래스 내(다른 패키지 가능)

자바 클래스 멤버

자바는 modifier를 붙이지 않을 시 default 설정이 적용되지만, 코틀린은 defaultpublic이다.

Modifier 접근 범위
public 어디서나
private 선언한 파일 내
internal 같은 모듈 내

코틀린 top-level

Modifier 접근 범위
public 어디서나
private 선언된 클래스 내
internal 같은 모듈 내
protected private + 서브 클래스 내

코틀린 클래스 멤버

코틀린 top-level에서는 protected modifier가 붙을 수 없다.

Primitive Type와 Wrapper Class

데이터 타입 크기(바이트) 내용
byte 1 -128 ~ 127 범위의 정수
short 2 -32,768 ~ 32,767 범위의 정수
int 4 -2,147,483,648 ~ 2,147,483,647 범위의 정수
long 8 -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 범위의 정수
float 4 소수 부분 6자리까지 오차없이 표현할 수 있음
double 8 소수 부분 15자리까지 오차없이 표현할 수 있음
boolean 1 참 또는 거짓
char 2 하나의 문자 또는 ASCII 값

자바 primitive 타입

자바에는 primitive 타입과 reference 타입이 존재한다. Primitive 타입은 위의 8가지로 실제 값을 스택에 저장한다. Reference 타입은 실제 값은 힙에 저장하고 그것을 가리키는 주소 값을 스택에 저장한다. Primitive 타입을 객체로써 저장하고 싶은 경우 각각의 타입에 해당하는 클래스가 존재하며 그것을 Wrapper 클래스라고 한다. Primitive 타입을 Wrapper 클래스로 변환하는 것을 Boxing, 그 반대를 Unboxing이라고 한다.

Primitive 타입 Wrapper 클래스
byte Byte
short Short
int Integer
long Long
float Float
double Double
boolean Boolean
char Character

Primitive 타입에는 null이 들어갈 수 없지만, Wrapper 클래스는 가능하다.

데이터 타입 크기(바이트) 내용
Byte 1 -128 ~ 127 범위의 정수
Short 2 -32,768 ~ 32,767 범위의 정수
Int 4 -2,147,483,648 ~ 2,147,483,647 범위의 정수
Long 8 -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 범위의 정수
Float 4 소수 부분 6자리까지 오차없이 표현할 수 있음
Double 8 소수 부분 15자리까지 오차없이 표현할 수 있음
Boolean 1 참 또는 거짓
Char 2 하나의 문자

코틀린 데이터 타입

코틀린에는 이런 구분이 없고, 컴파일 시 상황에 따라 자바의 primitive 또는 wrapper 클래스로 자동으로 변환된다.

Comments