코틀린은 Intelij IDEA를 개발한 JetBrains에서 2011년에 공개한 오픈 소스 프로그래밍 언어이다.
JVM 기반의 언어이고 Java 문법과 유사하지만 더 간결한 문법과 다양한 기능을 추가한 언어이다.
Java와 상호 운용이 100% 지원 되는 점이 장점이다.
2017년에 구글에서 안드로이드의 공식 언어로 Kotlin을 추가하며 안드로이드의 대표 언어가 되었다.
안드로이드에서 많이 사용하는 만큼 코틀린 언어의 문법과 특징들을 알아 볼 것이다.
코틀린 데이터 타입
정수 데이터 타입
val number = 10
정수 데이터 타입은 정수를 저장하는데 이용된다. 코틀린은 8, 16, 32, 64비트 정수(Byte, Short, Int, Long)를 지원한다.
부동소수점 데이터 타입
val number = 10.2313
부동 소수점 데이터 타입은 소수점 이하 자릿수를 포함한 값을 저장할 수 있다. 코틀린은 Float, Double 형식을 지원한다.
부울 데이터 타입
val bool = true
부울 데이터 타입은 참, 거짓 조건을 다루는 목적의 데이터 타입을 포함한다. true와 false 두개의 상숫값을 제공한다.
문자 데이터 타입
val sampleChar1 = 'a'
val sampleChar2 = '@'
val sampleChar3 = 'A'
val sampleChar4 = '\u0058'
문자 데이터 타입은 텍스트의 단일 문자를 저장하는데 이용한다. 유니코드를 이용해 문자를 참조할 수도 있다.
문자열 데이터 타입
val str = "This is string"
val longStr = """This is string,
but this is not string..
and this is integer!"""
val interpolationStr = "$str and $longStr is all string."
문자열 데이터 타입은 단어나 문장을 구성하는 일련의 문자이다. 삼중 따옴표를 사용하면 여러줄의 문자열을 선언할 수 있다.
문자열 보간(String Interpolation)을 이용해 여러 문자열, 변수, 상수, 함수등을 조합해 출력할 수 있다.
뮤터블 변수(Mutable Variable)
var count = 10
var count: Int
count = 42
뮤터블 변수는 var 키워드를 통해 선언하며, 생성시 값을 초기화할 수 있다.
초기값 없이 선언할 때는 타입을 함께 선언해야 한다.
이뮤터블 변수(Immutable Variable)
val count = 20
val count: Int
count = 20
이뮤터블 변수는 종종 상수라 불리며 한번 값을 할당한 이후에는 더 이상 변경할 수 없다.
코틀린 코드를 작성할 때는 항상 뮤터블 변수보다 이뮤터블 변수가 우선해야 한다.
데이터 타입은 객체다
val str = "This is string"
val uppercase = str.toUpperCase()
val length = str.length
val result = str.contains("string")
앞에서 설명한 모든 데이터 타입은 객체이며 점 표기법을 이용해 접근 가능하다.
타입 애너테이션과 타입 추론
코틀린은 정적 타입 프로그래밍 언어로 분류된다. 변수의 데이터 타입이 식별되면 변수에 다른 타입의 데이터를 지정할 때 컴파일 오류가 발생한다. 따라서 타입을 직접 지정해주어야 한다.
val count: Int = 10
val title: String
if (count == 10) {
title = "iOS"
} else {
title = "Android"
}
타입 애너테이션을 이용해서 변수 타입을 지정하는 방법이 있다.
만약 타입 애너테이션이 없으면 코틀린 컴파일러에서 타입 추론 기법을 이용해 변수 타입을 식별한다.
상수 선언 시 타입 애너테이션만 입력하면 이후 코드에서 값을 할당할 수 있다.
널 허용 타입(Nullable Type)
널 허용 타입은 대부분의 프로그래밍 언어에는 존재하지 않는 개념이다. (Swift의 옵셔널 타입 제외)
변수에 null 값이 할당될 수 있는 상황을 안전하고 일관적으로 처리하는 기법이다.
기본적으로 코틀린에서 변수에는 null 값을 할당할 수 없다.
val str: String = null
//Error: Null cannot be a value of a non-null string type String
val str: String? = null
변수에 null 값을 저장하도록 할 때는 타입 선언 뒤에 ?를 입력해서 널 허용 타입임을 구체적으로 선언해야 한다.
val str: String? = null
if (str != null) {
val anotherStr: String = str
}
널 허용 타입 변수가 아닌 변수에 널 허용 타입 변수를 할당하기 위해서는 null 여부를 확인하는 코드를 추가해야 한다.
안전 호출 연산자
널 허용 타입 변수에 String 객체인 toUpperCase() 함수를 호출하게 되면 다음과 같은 에러가 나온다.
val str: String? = null
val uppercase = str.toUpperCase()
//Error: (Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?
이 경우 바로 위에 널 허용타입에서 봤던 것 처럼 null 여부를 체크하는 코드를 추가하면 된다.
하지만 이보다 훨씬 더 효율적인 방법은 다음과 같이 안전 호출 연산자(?.)를 이용해 함수를 호출하는 것이다.
val str: String? = null
val uppercase = str?.toUpperCase()
username 변수가 null이면 toUpperCase() 함수를 호출하지 않고 코드의 다음 행을 실행한다.
반면 null이 아닌 값이 할당되면 toUpperCase() 함수를 호출하게 된다.
not-null 어서션(not-null Assertion)
널 허용 타입에서 모든 컴파일러 제한을 제거하기 때문에 null 값이 할당된 경우에도 null이 아닌 형식과 동일한 방식으로 이용할 수 있다.
val str: String? = null
val uppercase = str!!.length
//Exception in thread "main" kotlin.kotlinNullPointerException
위 코드는 컴파일은 되지만 존재하지 않는 객체에서 함수를 호출하려고 시도했기 때문에 런타임에서 예외를 일으키게 된다.
이 문제는 널 허용 타입을 이용해 피하도록 디자인됐기 때문에 일반적으로 not-null 어서션의 사용은 권장하지 않으며, 값이 확실하게 null이 아닌 상황에서만 이용해야 한다.
널 허용 타입과 let 함수
null이 아닌 파라미터를 받는 함수에 널 허용 타입의 인수를 전달해도 위와 같은 유사한 문제가 발생한다.
val number = 10
val count: Int? = 20
val result = number.times(count)
print(result)
//Error: Type mismatch: inferred type is Int? but Int was expected
이 문제를 해결하기 위해서 null 여부를 if문을 통해 체크하면 해결되지만 let 함수를 이용하면 더 편리하게 해결할 수 있다.
count?.let {
val result = number.times(it)
print(result)
}
let 함수는 널 허용 타입을 null이 아닌 변수로 변환하고 람다 구문 안에서 참조할 수 있는 it을 붙인다.
초기화 지연
코틀린의 변수는 선언시 초기화해야 하는데 변수 값을 코드 실행의 나중 시점까지 알 수 없는 경우에는 불편할 수 있다.
lateinit var name: String
name = "Sangyoon Chae"
lateinit 수정자를 이용해 변수를 선언하면 값이 나중에 초기화되도록 지정할 수 있다.
물론 초기화 전에 해당 변수에 접근하면 예외가 발생한다.
이럴 때 lateinit 변수의 초기화 여부는 isInitialized 프로퍼티를 이용해 확인할 수 있다.
if (::name.isInitialized) {
print("name")
}
엘비스 연산자
엘비스 연산자는 값 또는 표현식의 결과가 null인 경우에 반환할 기본값을 정의할 수 있다.
return str ?: "String is null"
타입 캐스팅 및 타입 확인
코틀린 컴파일러가 객체 타입을 추론할 수 있지만 값 타입이 모호하거나 함수 호출 시 지정되지 않은 객체가 종종 반환되는 경우에 타입을 식별할 수 없는 상황이 발생한다.
이럴 때 컴파일러에게 예상되는 객체 유형을 알려주는 것을 타입 캐스팅이라 부르며 as 연산자를 이용해 수행한다.
is 연산자를 사용하면 객체가 특정 타입을 준수하는지 확인할 수 있다.
val keyMgr = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager //non-nullsafe 캐스팅
val keyMgr = getSystemService(Context.KEYGUARD_SERVICE) as? KeyguardManager //nullsafe 캐스팅
if (keyMgr is KeyguardManager) {
//code...
}
코틀린 기본 문법(1) - 코틀린 데이터 타입, 변수, 널 허용
'Kotlin' 카테고리의 다른 글
[Kotlin] 코틀린 특수 타입 (Any, Unit, Nothing) (1) | 2023.07.09 |
---|---|
[kotlin] 코틀린 기본 문법(3) - 코틀린 객체지향 프로그래밍, 상속과 서브클래싱 (0) | 2023.06.02 |
[Kotlin] 코틀린 기본 문법(2) - 코틀린 연산자와 표현식, 제어 흐름, 함수와 람다 (0) | 2023.05.28 |