코틀린(kotlin)이란? 변수 및 함수 특징

wooSim·2023년 7월 16일
0

kotlin Study Lab

목록 보기
1/2

📜 Kotlin이란?

백엔드 개발 또는 서버 개발자 채용 공고에 java 언어와 더불어 kotlin 언어가 나옵니다.

Kotlin은 Intellij로 유명한 jetbranins에서 개발한 언어로 2017년 구글 I/O행사에서 안드로이드 고식언어로 코틀린을 지정하며 인기가 많아졌습니다. Kotlin이 안드로이드 개발에서 유명하지만 서버측 자바 웹 어플리케이션 개발에도 많이 사용됩니다.

Kotlin은 함수형 언어, Lamdas, Extension, Null Safety등 최신 언어 트랜드를 지원합니다. Kotlin은 별도의 실행 환경을 제공하지 않고 java의 실행환경인 JVM을 그대로 이용합니다. Java언어를 100% 호환 가능하며 그렇기 때문에 java로 개발하던 안드로이드, spring에서도 가장 많이 사용되고 있습니다. (javascript, ios도 개발이 가능하다고 합니다. )

📜 Kotlin 특징

  1. Null 안전성(Null Safety) 한 언어
    • 코틀린에서 null이 없다는 것이 아닙니다! 컴파일러가 NPE가 발생하지 않도록 신경써주며 많은 것일 지원해줍니다.
  2. 함수형 프로그래밍(FP)을 완벽하게 지원
    • java 언어에서도 함수형 프로그래밍을 지원하지만 한계가 있습니다. 코틀린은 완벽히 함수형 프로그래밍을 지원하며 컴파일 시에 java 언어로 변환됩니다.
  3. data 클래스의 단순화
    • java 언어 vo 클래스를 작성한다면 getter, setter를 만들고 equals(), toString() 등 override 받아야 합니다. 하지만 코틀린에서는 data 키워드 하나로 이 모든 코드를 생략해도 됩니다!
  4. immutable 변수 (불변 변수)
    • 변수에 값이 변하지 않는 다는 것은 아주 중요합니다. 코틀린에서는 변수 선언할 때 부터 mutable, immutable 변수를 구분하여 선언합니다.

이외에도 클래스에 주 생성자, sealed Class, property 등 다양한 특징이 있습니다.



📜 Kotlin 파일 구성


Java에서는 AAA.class 파일을 만들면 해당 파일은 public class AAA{...} 안에 변수나 함수를 사용할 수 있습니다. 한마디로 class 만 Top level에 선언할 수 있는 것이죠.

//컴파일 오류
//int num =1;

public class Test {

    public static void main(String[] args){
        int num =1;
        System.out.println("Hello world " + num );
    }
}

// 결과 : Hello world 1

하지만 kotlin에서는 top level에 함수, 변수 클래스 모두 사용가능하며 함수안에 클래스가 있을수 있습니다.

package ch2

val num: Int = 1;

fun main() {
    println("Hello world ${num}")

    class SubMain{

    }
}

// 결과 : Hello world 1

참고로 Kotlin에서는 굳이 ;(세미콜론)을 붙이지 않아도 됩니다.



📜 변수 및 함수 선언


○ 변수 선언

Kotlin에서 변수 선언할 때 val 혹은 var 를 사용합니다.

class AAA {
    val data1: Int = 10
    val data2 = 20
    var data3 = 30
}

data1 처럼 타입을 명시하고 초기값을 줘도 되지만 data2, data3처럼 타입이 없을 경우에도 초기값에 따라 적절한 타입이 적용됩니다. 이러한 기법을 타입 추론이라고 합니다.

여기서 data2와 data3의 값을 변경해보면 어떻게 될까요?

data2에서 에러가 발생합니다. 그 이유는 val 과 var의 차이에 있습니다.

  • val : value를 뜻하며 값 변경이 불가능
  • var : variable를 뜻하며, 값 변경이 가능

그렇기 때문에 val로 선언된 data2의 값을 변경을 할려고 하면 에러가 발생합니다.

하지만 주의할 사항으로 val가 상수 변수를 뜻하는 것은 아닙니다. 상수 변수는 java에서 final 키워드를 사용하듯이 kotlin에서는 const 키워드를 사용합니다.

예를 들어 java에서 상수 변수를 선언할 때 public static final int MIN_VAL = 10; 으로 선언한다면 kotlin에서는 const val MIN_VAL = 10으로 사용하면 됩니다. (kotlin에는 static 키워드가 없습니다.)

const val data4: Int = 40
//const var data5: Int = 50 -> 에러

상수 변수는 값이 변경되지 않는 변수이기 때문에 당연히 var 키워드와 함께 사용할 수 없습니다.
그렇다면 val 와 const의 차이점은 무엇일까요??

  • const: 항상 같은 값을 참조
  • val : 값 변경은 불가능하지만 변수가 항상 그 값을 참조 보장하지는 않음

여기서 kotlin에서 프로퍼티라는 개념이 나옵니다.

○ 프로퍼티

kotlin에서 val와 var를 사용한 변수를 프로퍼티(Property)라고 부릅니다. 변수처럼 보이지만 접근자라고 불리는 getter와 setter 함수가 내장되어 있기 때문입니다.

class AAA {
    /*val data2 = 20
    var data3 = 30*/
  
    val data2 = 20
        get() = field
    
    var data3 = 30
        get() = field
        set(value) {field = value}
}

주석으로 처리된 문장은 아래에 있는 getter와 setter를 내장하고 있는 코드와 같은 것입니다.

class AAA {
    /*val data2 = 20
    var data3 = 30*/
  
    val data2 = 20
        get() = field
    
    var data3 = 30
        get() = field
        set(value) {field = value}
}

여기서 getter를 커스텀해서 사용할 수도 있는데 만약 getter를 이런식으로 구현 했따면 처음 초기값과 실제로 사용할 때 참조하는 값은 충분히 달라질 수도 있습니다.

class AAA {
    var flag = false

    val data2 = 20
        get() {
            if(flag)
                return field
            else
                return 2000
        }
}

fun main(args: Array<String>) {
    val aaa = AAA()
    println("data2 : ${aaa.data2}")
}
// 결과
// data2 : 2000

에러를 피하기 위해 모든 변수를 var로 선언하는 것은 좋지 않습니다. var는 mutable(변경이 가능)한데 데이터가 변경이 가능하냐 안하냐는 중요한 부분 입니다. 기본적으로 val로 선언하고 변경에 한해서만 선별적으로 var로 선어하는 것을 권장합니다.


○ 함수 선언

코틀린에서는 함수를 선언할 때 fun이라는 키워드를 사용합니다.

/// fun 함수명(매개변수명: 타입) : 반환타입 { ... }
fun sum(a: Int, b: Int) : Int{
	return a + b
}

참고로 매개변수 부분에는 var, val을 선언할 수 없습니다. 무조건 val로 적용되어 매개변수를 변경할 수 없게 합니다.

만약 반환 값이 없는 경우에는 Unit으로 명시하며 생략가능합니다.

fun print1(a: Int, b: Int) : Unit{
	println("...")
}

fun print2(a: Int, b: Int) {
	println("...")
}

함수형 프로그래밍을 지원하는 언어이기 때문에 함수안에 함수를 정의 가능

fun sum(a: Int, b: Int) : Int{
    var sum = 0
    fun calSum(){
        for(i in a..b){
            sum += i
        }
    }

    calSum()
    return sum
}
fun main(args: Array<String>) {
    println(sum(1, 5))
}
//결과 
// 15

📜 Null Safety (Null 안전성)


○ 변수 초기화

Kotlin에서 변수의 선언을 top-level, 클래스 내부, 함수 내부에서 할 수 있습니다. 이 중에서 top-level과 클래스의 멤버 변수는 반드시 선언과 동시에 초기화를 해주어야 합니다.

참고로 함수의 지역변수도 선언과 동시에 초기화 하지 않더라도 이후에 초기화 해주어야만 사용할 수 있습니다.

그런데 만약 변수 선언에 초기값을 대입할 수 없을 경우에는 ??

○ Null 안전성

Kotlin의 특징 중 하나가 Null Safety(Null 안전성)하다는 것 입니다. 이는 null이 없다는 표현이 아닌 컴파일러가 NullPointException(NPE)를 신경쓰며, Null에 대한 다양한 처리를 도와줌으로써 NPE 가 발생하지 않는 프로그램을 작성할 수 있게 해주는 것입니다.

코틀린에서는 타입을 선언할 때 부터 Null을 허용할 지(nullable) Null을 불허할지(non-null) 구분합니다.

// val data1 : String  = null ->  에러
val data1 : String  ?= null  

var data2 : String = "woo"
// data2 = null ->  에러

위처럼 프로퍼티를 선언할 때 타입 뒤에 ? 를 쓰면 nullable하며, ? 를 쓰지 않으면 non-null이기 때문에 null로 값 변경도 불가능 합니다.

만약 nullable하게 선언하였다면 NPE 발생 가능성이 있는데 kotlin에서는 NPE를 방지할 다양한 기법을 제공합니다.

  • Null 확인 연산자(?.)
fun main(args: Array<String>) {
    var data1: String ?= "woo"

    var len: Int ?= data1?.length
    println(len)

    data1 = null
    len = data1?.length
    println(len)
}
//결과 
// 3
// null

만약 data1이 null이 아니면 연산을 수행하며 null일 경우 그냥 null을 반환해줍니다.

  • 엘비스 연산자(?:)
fun main(args: Array<String>) {
    var data1: String ?= "woo"

    var len: Int ?= data1?.length ?: -1
    println(len)

    data1 = null
    len = data1?.length ?: -1
    println(len)
}
//결과 
// 3
// -1

엘비스 연산자(?:)는 null 확인 연산자와 다르게 null일 경우 대입해야하는 값이나 구문을 사용할 수 있습니다.

  • 예외 발생 연산자(!!)
fun main(args: Array<String>) {
    var data1: String ?= null

    data1!!.length
}
//결과
// Exception in thread "main" java.lang.NullPointerException..

null 확인 연산자(?.)나 엘비스 연산자(?:)와는 다르게 NPE를 발생시키는 연산자 입니다.



data class User(val name: String, val age: Int)
profile
daily study

0개의 댓글