안드로이드 개발하는 kancho 입니다.
좋은 기회로 코틀린을 다시 복습하는 시간을 가지게 되어 코틀린을 정리하려고 합니다.
코틀린은 안드로이드 플랫폼의 공식 언어이기도 하면서 안전성과 간결성, 상호 운용성을 강조하는 언어입니다.
또한, 자바와 마찬가지로 JVM에서 동작하는 프로그래밍 언어입니다.
이번 포스팅에서는 코틀린의 기본적인 문법에 대해 정리하려고 합니다. '코틀린 완벽 가이드' 책을 참고하였습니다.
1) 주석
코드에 대한 설명이나 문서화를 위해 사용합니다.
- 한 줄 주석( // )
- 여러 줄( /* */ )을 사용할 수 있는 주석
// 이름
val name = "kancho"
/*
이름은 kancho 이다
lastName 은 lastName 변수를 보면 알 수 있다.
*/
val firstName = "kancho"
간단한 주석은 가독성에 도움이 되지만 복잡한 주석은 오히려 가독성을 해칠 수 있어 적절하게 사용하는 것이 좋다.
2) 변수
변수는 데이터 값을 저장하기 위해 할당받은 메모리 공간을 의미한다.
- val (immutable) - 읽기만 가능
- var (mutable) - 읽기, 쓰기 모두 가능
val(value) 키워드는 불변 변수이다. 변수를 초기화하면 값을 변경할 수 없다.
자바의 final과 같은 역할이다.
var(variable) 키워드는 가변 변수이다. 변수를 초기화한 이후 값을 변경할 수 있다.
val name = "kancho"
name = "cookie" // 컴파일 에러. val -> 불변
var firstName = "kancho"
firstName = "cookie" // 성공. var -> 가변
var 변수는 값이 변화될 가능성이 있으므로 필요한 곳에만 사용하고 안정성을 위해 되도록 val 변수를 사용하면 좋습니다.
3) 식별자 (identifier)
데이터를 구별할 수 있는 이름이다.
- 문자, 숫자, 언더바(_)로 구성 (숫자만으로는 사용 X)
- hard keyword는 사용할 수 없다
- $ 기호를 사용할 수 없다
val name = "kancho" // 성공
val 123 = "kancho" // 컴파일 에러
val fun = "kancho" // hard keyword 사용, 컴파일 에러
val import = "kancho" // soft keyword 사용, 성공
4) 연산자 (operators)
대입, 논리, 산술 등등의 연산자가 있다.
val sum = 1 + 2 // 3
위 식(statement)에서 sum 변수는 + 연산자를 통해 1과 2의 합인 3의 값을 갖는다.
- 연산자 우선순위
분류 | 연산자 | 예제 | 해석 |
후위 | ++ -- . | a*b++ , ++b-- | a*(b++) , ++(b--) |
전위 | + - ++ -- ! | +a*b , !a || b | (+a)*b , (!a) || b |
곱셈 | * , / , % | a*b+c | (a*b)+c |
덧셈 | +, - | a + b and c | (a+b) and c |
중위 | 이름이 붙은 중위 연산자 | a < b or b < c | (a < (b or b)) < c |
비교 | <,>, <=, >= | a<b == b<c | (a<b) == (b<c) |
동등 | ==, != | a==b || b!=c | (a==b) || (b!=c) |
논리곱 | && | a || b && c | a || (b && c) |
논리합 | || | a && b || c | (a && b) || c |
대입 | =, +=, -=, *=, /=, %= | a = b*c | a = (b*c) |
식이 길어지고 많은 연산자가 필요할 때 우선순위를 고려해서 코드를 작성해야 한다.
5) 기본 타입
Java에서는 원시 타입(primitive)과 참조 타입을 모두 사용하지만 코틀린에서는 모두 참조형 타입(reference)을 사용한다.
코틀린에서 기본 타입은 크게 4가지로 분류된다
- 정수를 표현하는 Byte, Short, Int, Long
- 실수를 표현하는 Double, Float
- 문자를 표현하는 Char
- 논리를 표현하는 Boolean
var one: Byte = 111 // 8bit (-128 ~ 127)
var two: Short = 22222 // 16bit (-32768 ~ 32767)
var three: Int = 3333333 // 32bit 정수 (-2^31 ~ 2^31 -1)
var four: Long = 123L // 64bit 정수 (-2^63 ~ 2^63 -1)
var five: Float = 12.3F // 32bit 부동소수점
var six: Double = 12.3 // 64bit 부동소수점, 부동소수점의 디폴트는 Double
var seven: Char = 'K' // 16bit 문자, '' 사이에 문자를 넣으면 된다
val isValid: Boolean = true // 1bit 논리
코틀린은 타입 추론 언어이기에 타입을 붙여주지 않아도 무방하다.
기본 타입들은 모두 비교 연산이 가능하다.
- == (같다), != (같지 않다), < (보다 작다), > (보다 크다), <= (보다 작거나 같다), >= (보다 크거나 같다)
- But, 서로 같은 타입일 때만 ==, != 를 허용한다
주의할 점은 큰 타입이 명시된 변수에 작은 타입의 값을 넣을 수 없다는 것이다.
val intNum = 100
val longNum: Long = intNum // 컴파일 에러
그 외에도 최상위 타입인 Any가 있다. 다른 모든 타입은 Any의 하위 타입(subtype)이다.
val name: Any = "kancho" // String은 Any의 subtype
val num: Any = 1 // Int는 Any의 subtype
★ 참고
코틀린은 JVM 기반 언어이다. 원시 타입(primitive)이 참조 타입(reference)보다 속도가 빠르지만 코드가 실행될 때 코틀린 컴파일러가 내부적으로 원시 타입과 참조 타입으로 적절하게 대체하기 때문에 성능이 떨어지지 않는다.
7) 문자열
연속된 문자들로 이루어진 집합이며 String 타입으로 표현한다.
- 문자열 내의 문자는 불변 (immutable)
- "" 로 정의
- Escape 문자
- 문자열 템플릿 기능 - ${...}
- raw 문자열
- 연산자를 통한 연결 (concatenate)
val hello = "Hello"
hello[0] = "K" // 컴파일 에러, 기본적으로 문자열 내 문자는 불변
val example = "Hello, my name is Kancho" // 그대로 출력
val example = "Hello \nmy name is Kancho" // escape 문자인 \n (newline) 으로 인해 줄바꿈
val age = 30
val example = "Hello my $age years old" // $를 이용한 문자열 템플릿
val name = "kancho"
val example = "Hello, my name is " + name // + 연산자를 통한 문자열 연결
val example2 = "Hello, my name is Kancho"
println(example == example2) // true, == 연산자를 통해 문자열의 내용을 비교
println(example === example2) // false, === 연산자를 통해 변수가 참조하는 위치를 비교
val example = """ // escape를 사용하지 않고 줄바꿈이 가능
Hello, my name is kancho,
and I am $age years old
"""
★ 이스케이프(Escape) 문자
코틀린에서는 문자열을 사용할 때 특수 문자를 위해 이스케이프를 제공한다. 대표적으로
\t(탭), \b(백스페이스), \n(줄바꿈), \r(캐리지 리턴), \'(작은따옴표), \"(큰따옴표), \\(역슬래시), \$(달러 표시)가 있다.
- 동등성 비교
자바에서는 ==, != 연산자를 통해 변수가 참조하는 위치를 비교하고 equals()를 통해 값을 비교한다
하지만 코틀린에서는 ==, != 연산자를 통해 값을 비교하고 ===, !== 연산자를 통해 참조하는 위치를 비교한다
val str1 = "hello"
var str2 = "hello"
(str == str2) // kotlin에서는 true, Java에서는 false
- 다양한 함수 제공
함수 | 역할 |
isEmpty, isNotEmpty | 문자열이 비어있는지 검사 |
substring | 부분 문자열 추출 |
startsWith, endsWith | 접두사, 접미사 검사 |
indexOf | 인자로 받은 문자나 문자열에 대한 인덱스 반환 |
8) 배열
배열은 같은 타입의 데이터들이 모여있는 자료구조이다.
가장 기본적인 타입은 Array <T>이며 다양한 타입을 지원한다.
컴파일러가 배열에서 타입을 알 수 없는 경우 직접 명시해야한다
val arr1 = Array<String>() // 타입추론 불가능. 타입 지정
val arr2 = arrayOf("hello") // String으로 타입 추론
val arr1 = emptyArray<String>()
val arr2 = booleanArrayOf(false)
val arr3 = byteArrayOf(1)
val arr4 = shortArrayOf(1,2,3)
val arr5 = intArrayOf(1,2,3)
val arr6 = longArrayOf(1L,2L,3L)
val arr7 = charArrayOf('Z')
val arr8 = doubleArrayOf(1.5)
val arr9 = floatArrayOf(1.5f)
Array<T> 배열은 모든 값들을 객체로 박싱하기 때문에
ByteArray, ShortArray, IntArray, LongArray, FloatArray, DoubleArray, CharArray, BooleanArray의 특화된 배열을 사용하면 조금 더 효율적인 코드 작성이 될 수 있다.
배열 타입의 변수에는 실제 데이터에 대한 참조를 저장한다. 그래서 배열 변수에 다른 배열을 대입하면 같은 데이터를 공유한다.
별도의 배열을 만들기 위해서는 copyOf() 함수를 사용해야 한다.
val myName = arrayOf("kancho")
val name = myName
name[0] = "s"
println(myName) // "sancho"
val copiedName = myName.copyOf() // myName과 copiedName은 다른 곳을 참조한다
코틀린 배열에서는 자신의 타입을 제외하고는 다른 타입들과 하위 관계가 성립하지 않는다.
앞서 모든 타입은 Any의 하위 타입이라고 했지만 배열에서는 성립하지 않는다.
val names = arrayOf("a", "b", "c") // String 타입의 배열
val anyNames: Array<Any> = name // 컴파일 에러, String은 Any의 하위타입이지만 배열은 아니다
연산자를 사용한 배열
- ==, != 연산자는 참조 비교
- contentEquals() 함수는 값을 비교
val numArr = intArrayOf(1) + 2 // 1, 2
val concatArr = inArrayOf(3) + numArr // 3, 1, 2
val firstArr = intArrayOf(1,2,3)
val lastArr = intArrayOf(1,2,3)
(firstArr == lastArr) // false
firstArr.contentEquals(lastArr) // true
- 다양한 함수 제공
함수 | 역할 |
isEmpty, isNotEmpty | 배열이 비어있는지 검사 |
indexOf | 받은 인자와 일치하는 인덱스 반환 (없으면 -1) |
'코틀린' 카테고리의 다른 글
[코틀린] Scope function (영역 함수) (0) | 2022.10.10 |
---|---|
[코틀린] 확장 (Extension) (0) | 2022.10.10 |
[코틀린] Lazy 초기화 (0) | 2022.10.09 |
코틀린 정리 - (3) (0) | 2022.10.03 |
코틀린 정리 - (2) (0) | 2022.09.30 |