코틀린 간단한 개념
Kotlin의 특징을 정말 간단하고 보기 쉽게 정리하는 공간입니다.
람다 표현식을 지원한다.
스트림 API를 지원한다.
자바와 완벽하게 호환된다.
간결한 문법
- 세미 콜론을 사용하지 않는다.
- new를 사용하지 않고 객체를 생성.
- 타입 추론을 지원한다.
var: 수정 가능한 변수val: 수정 불가능한 값- 반복문은 for-each문만 지원한다.
널 안전성
- 널 값의 허용 여부를 명확히 검사한다.
- 컴파일 단계에서 검사한다.
1
2
3
4
// 널 값 허용
var a: String?=null
// 널 값 허용 X
var b: String = "b"
기본 자료형
타입 관련
- 모든 타입을 객체로 표현. (원시 타입과 래퍼 클래스를 구분하지 X) 사실, 원시 타입을 모두 객체로 처리하면 비효율적이다. 코틀린은 코드를 작성하는 시점에 원시 타입과 래퍼를 구분하지 않지만, 컴파일 단계를 거치면서 가장 효율적인 타입으로 변환된다.
- 값이나 변수의 타입으로 사용되는 경우 : 원시 타입으로 변환
- 컬렉션의 타입 인자로 사용되는 경우 : 래퍼로 변환
1
2
3
4
5
var a: Int = 2 var b: List<Int> = ...
// 아래와 같이 변환된다.
int a = 2; List<Integer> b = ..
문자 관련
- 문자에 해당하는 아스키 코드를 char에 숫자 형태로 대입하지 못한다. 컴파일 에러가 발생한다.
- toChar() 함수를 사용해 다른 자료형의 값을 문자 자료형으로 대입한다.
1
2
3
val code: Int=65
// code에 해당하는 문자를 할당한다.
val ch: Char = code.toChar()
문자열 관련
- 문자열의 특정 문자에 접근할 때 get() 혹은 대괄호([])와 인덱스를 사용해 접근한다.
- 문자열 템플릿을 사용해 템플릿 문자열 내에 직접 인자를 대입한다.
- 인자로 값이나 변수 대신 표현식을 넣을 경우
중괄호{}로 구분한다.
- 인자로 값이나 변수 대신 표현식을 넣을 경우
1
2
3
4
5
6
val foo: String = "Victory" val ch1: Char = foo.get(0) // V
val ch2: Char = foo[1] // i
val length: Int = 10
val lengthText: String = "Length: $length meters"
val text = "Length : ${foo.length}"
배열
- 타입 인자를 갖는 Array 클래스로 표현한다.
- arrayOf() : 코틀린 표준 라이브러리에 포함. 입력 받은 인자로 구성된 배열을 생성.
- 자바의 원시 타입은 코틀린 배열 클래스의 타입 인자로 사용할 수 없다.
- 자바 원시 타입을 인자로 갖는 배열을 표현하기 위해서는 원시 타입에 대응하는 특수한 클래스를 사용해야 한다.
1
2
3
4
5
6
val words: Array<String> = arrayOf("a","b")
// 원시 타입의 배열
val intArr: IntArray = intArrayOf(1,2,3)
// wrapper 타입의 배열
val IntArr2: Array<Int> = arrayOf(1,2,3)
컬렉션
- JVM을 기반으로 하므로 컬렉션은 자바에서 제공하는 클래스들을 그대로 사용한다.
- 컬렉션 내 자료의 수정 가능 여부에 따라 컬렉션의 종류를 구분한다.
- Collection, List 인터페이스에는 자료를 조회하는 함수만 포함되어 있으므로 자료가 할당되면 수정이 불가능하다.
- MutableCollection, MutableList 인터페이스에는 자료를 수정하는 함수가 포함되어 있다.
- set, map 도 동일한 규칙이 지정된다.
- listOf, setOf, mapOf : 자료의 수정이 불가능하다.(불변 - immutable)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 자료의 수정이 불가능함. immutable하다.
val immutableList: List<String> = listOf("a","b")
// get(0)과 동일.
val firstItem: String= immutableList[0]
// 컴파일 오류 발생.
immutableList[0] = "c"
val immutableMap : Map<String, Int> = mapOf(Pair("A", 65) , Pair("B", 66))
// 키 "A"에 해당하는 값 - get("A")과 동일.
val code: Int = immutableMap["A"]
// 불변이므로 컴파일 에러.
immutableMap["C] = 67
val mutableMap : HashMap<String, Int> = hashMapOf(Pair("A",65),Pair("B",66)) // 가변이므로 가능.
mutableMap["C"] = 67
// 조금 더 간단하게 Pair 표현 // key to value 형태.
val map : Map<String, Int> = mapOf("A" to 65, "B" to 66)
클래스 및 인터페이스
디폴트가 public이다.
선언된 내용이 없으면 몸체만 선언할 수 있다.
new를 사용하지 않고 인스턴스를 생성.
추상 클래스와 인터페이스는 인스턴스를 생성하는 형태가 자바와 조금 다르다.
추상 클래스에서는 인스턴스를 생성 시 생성자를 사용하지만, 생성자가 없는 인스턴스 생성 시 인터페이스 이름만 사용한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
abstract class Foo{ abstract fun bar() } // object: 생성자 val foo = object: Foo(){ override fun bar(){ // 함수 구현. } } interface Bar{ fun baz() } // object: 인터페이스 이름 val bar = object: Bar{ override fun baz(){ // 함수 구현. } }
프로퍼티
- 자료를 저장할 수 있는 필드와 이에 상응하는 getter/setter 메소드를 함께 제공한다.
- 클래스의 멤버로 사용하는 프로퍼티는 초기값을 명시적으로 지정해야 한다. 그렇지 않을 시 컴파일 에러 발생.
- 단, 생성자에서 프로퍼티의 값을 할당한다면 선언 시 값을 할당하지 않아도 된다.
- 프로퍼티 선언 시점이나 생성자 호출 시점에 값을 할당할 수 없는 경우
lateinit키워드를 사용해 프로퍼티의 값이 나중에 할당될 것임을 명시한다.lateinit키워드는 var 변수에만 사용 가능.- 반드시 초기화 해야 한다.
- 프로퍼티에 초기값을 할당하는 시점에서 해당 프로퍼티의 타입을 추론할 수 있다면 타입 선언 생략 가능.
- lazy : 사용 시점(참조 시점)에 메모리에 할당. 선언하고 참조하지 않으면 메모리 할당하지 않음.
1
2
3
4
class Person{
lateinit var gender: String
// 선언 시점에 값을 할당하지 않아도 컴파일 에러 발생 X.
}
주의할 점이 하나 있다.
lateinit 키워드를 사용했는데, 초기화 하지 않으면 Uninitialized PropertyAccessException 예외가 발생한다. 컴파일 단계에서는 확인이 불가능하므로 lateinit 키워드를 사용할 경우 반드시 초기화 여부를 확인하는 것이 좋다.
1
2
3
4
5
6
7
8
lateinit var name: String
// 초기화가 되었는지 확인할 수 있다.
if(::name.inInitialized){
println("초기화O")
}else{
println("초기화X")
}
This post is licensed under CC BY 4.0 by the author.