코틀린과 자바
안드로이드 개발 공부를 늦게 시작하여 코틀린으로 했지만, 코틀린 이전의 코드들은 전부 자바 코드여서 자바도 어느 정도 이해를 하고 있어야 한다. 비슷한 두 언어 자바와 코틀린의 공통점과 차이점을 몇가지 정리해보려 한다.
공통점
JVM
JVM(Java Virtual Machine)은 자바를 구동하는 가상 머신이다. 자바와 코틀린 모두 컴파일러가 JVM에서 구동되는 자바 바이트코드로 변환하여 사용된다(코틀린 네이티브를 사용하면 네이티브로 컴파일해 JVM 없이 구동할 수도 있다).
코틀린 코드 |
바이트코드 |
디컴파일된 자바 코드 |
코틀린은 자바 바이트코드로 변환되기 때문에, 자바에 없는 함수를 바이트코드로 변환 후 자바로 디컴파일해서 보면 어떤 식으로 동작하는지 파악할 수 있다.
자바 라이브러리 사용
공통점이라기보단 코틀린과 자바가 100% 호환되기 때문에 가능한 코틀린의 장점이다. 안드로이드 개발을 하다 보면 많은 라이브러리들이 자바로 짜여져 있는데, 코틀린으로 개발하는 안드로이드 앱에서 그러한 라이브러리들이 사용 가능하다. 심지어 한 프로젝트 내에 코틀린과 자바 둘 다 사용할 수도 있다.
코틀린 코드에서 Glide 라이브러리를 사용 |
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 설정이 적용되지만, 코틀린은 default가 public
이다.
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