728x90

구글이 2017년 5월 18일 안드로이드 공식 언어로 코틀린(Kotlin) 추가해서 현재 Android 개발은 Java 와 Kotlin 이 공존하고 있는데, 향후에는 Kotlin 으로 전부 대체될 것으로 보인다.

GitHub 에서 source code를 검색하면 Kotlin 으로 된 코드들이 검색되어 안배우면 안되겠다 싶어서 동영상 보면서 정리를 할 생각이다. 배울 언어가 너무 많아서 안배우고 싶은데, 안배우면 도태될 거 같아서....

 

Kotlin 은 IntelliJ IDE를 만든 JetBrains 에서 개발한 오픈소스 언이이다.

JVM에서 동작하고 Java 와 100% 호환된다.

Java 코드를 Kotlin 에서 인식하고, Kotlin 코드를 Java 에서 인식한다.

 

- Java 플랫폼에서 숫자형은 JVM primitive type 으로 저장됨
- Nullable 이나 제네릭의 경우에는 박싱됨
- 박싱된 경우 identity를 유지하지 않음.
- 문자(Characters) : 숫자로 취급하지 않음.

 

개발툴 다운로드

- 온라인에서 코드 테스트 : https://play.kotlinlang.org/ 에서 간단한 코드를 연습할 수 있다.

- Intellij IDEA 개발툴 : https://www.jetbrains.com/ko-kr/idea/ 에서 community 무료버전을 다운로드 받아서 설치한다.

  Java 에 대한 코드 연습을 Eclipse 툴에서 하듯이

  유투브 강좌 등에서 설명하는 코틀린 문법 연습은 IntelliJ IDEA 툴에서 하면 된다.

  Android Studio 에서 코틀린 선택하여 코드 연습하는 것은 적절하지 않다.

TOOL을 Jetbrains 에서 만들어서 Android Studio 와 메뉴구조는 비슷하다.

잠깐 써본 PHPStorm 도 메뉴구조가 거의 동일하더라.

 

변수의 선언

Java에서는 변수를 선언할 때 타입이 맨 앞에 온다. 코틀린에서는 타입 지정을 생략하는 경우가 흔하다.
Java에서는 두가지종류의 변수가 있는데 하나는 primitive type(기본형)이 있고 다른 하나는 레퍼런스 타입(객체형)이 있다. 코틀린에서는 이 모든게 통합됬다. 즉 레퍼런스 타입밖에 없다.
 

Java에서는 기본이 변수고 상수는 final을 붙혀서 표시했다.

코틀린에서는 변수는 var로 상수는 val로 표시한다.

val // 변경 불가능한 참조를 저장하는 변수다. 선언시에만 초기화 가능. 중간에 값을 변경할 수 없다.

var // 변경 가능한 참조다. 일반적으로 통용되는 변수, 언제든지 읽기쓰기가 가능하다.

 

 

기본적으로 모든 변수를 val 키워드를 사용해 불변 변수로 선언하고, 나중에 꼭 필요할 때에만 var 변수로 변경하라.

코틀린은 문장의 끝에 세미콜론을 사용하지 않는다.

코틀린은 기본변수에서 null 을 허용하지 않으며, 또한 변수에 값을 할당하지 않은채로 사용하게 되면 문법 에러를 표시하고 컴파일을 막아주므로 의도치 않은 동작이나 null pointer exception 등을 원천적으로 차단해 준다는 장점이 있다.

 

var a = 100

또는

var a: Int  // 초기화 식을 사용하지 않고 변수를 선언하려면 변수 타입을 반드시 명시해야 한다.

a = 100

 

※ var 키워드를 사용하면 변수의 값은 변경할 수 있지만 변수의 타입은 고정돼 바뀌지 않는다.

var a = 100

a = "kotlin"  ← 컴파일 오류 발생

컴파일러는 변수 선언 시점의 초기화 식으로부터 변수의 타입을 추론한다.

 

var a: Int? // 코틀린에서 null 값을 허용하려면 자료형의 오른쪽에 ? 기호를 붙여준다.

 

문자형 : 코틀린은 문자열을 유니코드 인코딩 방식 UTF-16 BE 을 사용하여 글자 하나당 2bytes 메모리 공간을 차지한다.

var a = '가' // 문자 한글자는 작은 따옴표 사용한다.

var a ="홍길동" // 문자열을 쌍따옴표를 사용한다.

var a ="""여러줄의

   문자열"""  // 쌍따옴표 3개를 사용하면 여러줄 문자열 가능하며, 줄바꿈이나 특수문자까지 사용 가능하다.

 

lateinit 키워드를 사용한 늦은 초기화

코틀린에서는 클래스의 변수(var, val로 선언되는 변수들)를 프로퍼티(Property)라 부른다.

코틀린에서는 일반적으로 생성자에서 모든 프로퍼티를 초기화해야 한다.

프로퍼티 타입이 null이 될 수 없는 타입이라면 반드시 null이 아닌 값으로 그 프로퍼티를 초기화해야 한다.

private var backPressHandler: BackPressHandler? = null

// null로 초기화하기 위해 null이 될 수 있는 타입인 프로퍼티를 선언한다.

backPressHandler!!.onBackPressed()

// 반드시 null 가능성을 신경써야 한다. non-null 단언 연산자 !!를 꼭 써야 한다.

 

lateinit 변경자를 붙이면 프로퍼티를 나중에 초기화할 수 있다.

private lateinit var backPressHandler: BackPressHandler

// 초기화를 하지 않고 null이될 수 없는 프로퍼티를 선언한다.

backPressHandler.onBackPressed()

 

lateinit은 다음 조건에서만 사용할 수 있다.
1) var 변수에서만 사용한다.
2) null 값으로 초기화 할 수 없다.
3) 초기화 전에는 변수를 사용할 수 없다.
4) Int, Long, Double, Float에는 사용할 수 없다.

5) lateinit은 custom getter/setter를 사용하지 않은 프로퍼티에만 사용할 수 있다.

문자열 접합 연산

println("안녕하세요, $name!")  → Java의 문자열 접합 연산 ("안녕하세요," + name + "!")와 동일한 기능

 

존재하지 않는 변수를 문자열 템플릿 안에서 사용하면 컴파일 오류가 발생한다.

$ 문자를 문자열에 넣고 싶다면 println("\$x")와 같이 \를 사용해 $를 이스케이프 시켜야 한다.

${name} 처럼 중괄호로 변수명을 감싸는 습관을 들이면 좋다. 이렇게 하면 복잡한 식도 중괄호로 둘러싸서 문자열 템플릿안에 넣을 수 있다.

 

 

형변환

코틀린에서는 Int 형과 Long 형 타입이 다른 경우 자동으로 형변환이 되지 않는다

즉, 다른 언어들이 지원하는 암시적 형변환은 지원하지 않고, 명시적 형변환만 지원한다.
  var a: Int = 100
  var b: Long = a.toLong()

 

배열

배열은 Array 클래스로 표현된다.

var intArr = arrayOf(1, 2, 3, 4, 5)  // arrayOf 함수를 통해 배열에 저장할 값들을 나열한다.

var intArr = arrayOfNulls<Int>(10) // null 로 채워진 배열. 

 

함수

function 의 약자인 fun 을 사용한다.

 

리턴과 파라미터가 없는 함수
fun 함수이름() { }

값을 리턴 하는 함수
fun 함수이름() : 리턴타입 { return 값 }

리턴과 파라미터가 있는 함수
fun 함수이름( 변수이름: 변수타입) : 리턴타입 { return 값 }

fun add(a: Int, b: Int, c: Int): Int {   // 반환형

    return a + b + c

}

단일표현식 함수 

fun add(a: Int, b: Int, c: Int) = a + b + c  // 반환형의 타입 추론이 가능하여 반환형을 생략할 수 있다.

 

IF문

- val max = if( a > b) a else b

  Java 의 삼항연산자(ternary)가 코틀린에는 없음.

  int max = (a > b) > a : b; // Java 의 삼항연산자

- If식의 branches 들이 블록을 가질 수 있음 {  }

  val max = if(a > b) {

    print("Choose a")

    a

  } else {

    print("Choose b")

    b

  }

 

다중 조건문 when

- when문은 C계열 언어의 switch 문에 대응한다.

- when문은 각각의 branches의 조건문이 만족할 때까지 위헤서부터 순차적으로 인자를 비교함.

  when (x) {

     1 -> print("x == 1")

     2 -> print("x == 2")

     else ->{

           print("x is neither 1 nor 2)

     }

  }

- when이 식으로 사용된 경우 else 문이 필수임

- when 이 식으로 사용된 경우 컴파일러가 else문이 없어도 된다고 입증할 수 있는 경우에는 else 생략 가능

  var res = when (x) {

    true -> "맞다"

    false -> "틀리다"

  }

- branch의 조건문에 콤마를 사용하여 여러조건들을 처리할 수 있다.

  when (x) {

     0, 1 -> print("x == o or x == 1")

     else -> print("기타")

  }

- branch의 조건문에 함수나 식을 사용할 수 있다.

  when (x) {

     parseInt(x) -> print("s encodes x ")

     1 + 5 -> print("6")

     else -> print("s does not encode x")

  }

- range 나 collection 에 in 이나 !in 으로 범위 등을 검사할 수 있다.

  val validNumbers = listOf(3, 6, 9)

  when (x) {

    in validNumbers -> print("x is valid")

    in 1..10 -> print("x is in the range")

    !in 10..20 -> print("x is outside the range")

    else -> print("none of the above")

  }

- is 나 !is 를 이용하여 타입도 검사할 수 있다.

  fun hasPrefix(x: Any) = when (x) {

is String -> x.startsWith("prefix")

else -> false

  }

- when 에 인자가 없으면, 논리연산으로 처리된다.

  when {

x.isOdd() -> print("x is odd")

x.isEven() -> print("x is even")

  }

 

For Loops

- for문은 iterator 를 제공하는 모든 것을 반복할 수 있다

  for(item in collection)

      print(item)

- for문의 body가 블록이 올 수도 있다.

  for(item in collection) {

     print(item.id)

     print(item.name)

  }

- for(i in 0..9)  // 0부터 1씩 증가시키며 반복한다.

  for(i in 0..9 step 3)  

     print(i)    // 3씩 증가되어 0, 3, 6, 9 를 출력한다.

- 감소 반복

  for(i in 9 downTo 0)   // 9부터 1씩 감소하여 반복한다.

  for(i in 9 downTo 0 step 3)  // 9부터 3씩 감소하여 반복한다.

- 문자 for 문

  for(i in 'a'..'f')   // a부터 f까지 반복한다.

- 반복문 탈출 break

  loop@for(i in 1..10){

     for(j in 1..5) {

         if(i == 1 && j == 2) break@loop

         println("i : $i, j : $j")

     }

  }

 

fun main(args: Array<String>) {
    var a = listOf(1, 2, 3, 4, 5)
    println(a)
    println(sum(3 , 4))
    foo()
    println("")
    foo2()
    println("")
    foo3()
    println("")
    foo4()
    println("")
    println(foo5())
}

fun sum(a: Int, b: Int):Int {
    return a + b
}

fun foo() {
    var ints = listOf(0, 1, 2, 3)
    ints.forEach(
            fun(value: Int){
                if(value == 1) return
                print(value)
            })
    print("End")
}

fun foo2() {
    var ints = listOf(0, 1, 2, 3)
    // 람다식에서 return 시 nearest enclosing 함수가 return 된다.
    ints.forEach {
                if(it == 1) return
                print(it)
            }
    print("End")
}

fun foo3() {
    var ints = listOf(0, 1, 2, 3)
    // 람다식에 대해서만 return 하려면 label 을 이용해야 한다.
    ints.forEach loop@{
                if(it == 1) return@loop
                print(it)
            }
    print("End")
}

fun foo4() {
    var ints = listOf(0, 1, 2, 3)
    // 람다식에 대해서만 return 하려면 label 을 이용해야 한다.
    // 암시적 레이블은 람다가 사용된 함수의 이름과 동일하다.
    ints.forEach {
        if(it == 1) return@forEach
        print(it)
    }
    print("End")
}

fun foo5(): List<String> {
    var ints = listOf(0, 1, 2, 3)
    val result = ints.map{
        if(it == 0){
            return@map "zero"
        }
        "No $it"
    }
    return result
}
 

 

 

728x90

'안드로이드 > Kotlin 문법' 카테고리의 다른 글

코틀린 접근 제한자  (0) 2020.01.14
코틀린 패키지  (0) 2020.01.13
코틀린 인터페이스  (0) 2020.01.13
코틀린 추상클래스  (0) 2020.01.12
코틀린(Kotlin) 클래스 선언 및 상속  (0) 2020.01.12
블로그 이미지

Link2Me

,