ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 1. 코틀린에서 변수와 타입, 연산자를 다루는 방법
    Kotlin/자바 개발자를 위한 코틀린 입문 2023. 7. 5. 17:25

    1. 코틀린에서 변수를 다루는 방법

    1. 변수 선언 키워드 - var과 val의 차이점

    - java에서 long과 final long의 차이!

        ㆍ이 변수는 가변인가, 불변인가(read-only)

     

    - 코틀린에서는 모든 변수에 수정 가능 여부(var / val)를 명시해주어야 한다.

    fun main() {
        var number1 = 10L      // 바꿀 수 있는 변수
        val number2 = 10L      // 바꿀 수 없는 변수
    }

     

    - 코틀린에서는 타입을 추론해주지만 명시적으로 작성해줄 수도 있다.

    fun main() {
        var number1: Long = 10L      // 바꿀 수 있는 변수
        val number2: Long = 10L      // 바꿀 수 없는 변수
    }

     

    - 초기값을 지정해주지 않는 경우에는 타입을 명시해주고, 값을 넣어 주지 않고 사용하려고 하면 이 변수는 무조건 초기화 되어야 한다라는 에러가 발생.

    var number: Int
    println(a)	// 컴파일 에러 발생, Variable 'number' must be initialize

     

    - val 컬렉션에는 element를 추가할 수 있다.

    - 간단한 TIP

        ㆍ 모든 변수는 우선 val로 만들고 꼭 필요한 경우 var로 변경한다.

     

    2. Kotlin에서의 Primitive Type

    - Kotlin에서는 모두 Long인데? 성능상 문제는 없는 것인가?

        ㆍ숫자, 문자, 불리언과 같은 몇몇 타입은 내부적으로 특별한 표현을 갖는다.

        ㆍ이 타입들은 실행시에 Primitive Value로 표현되지만, 코드에서는 평범한 클래스처럼 보인다.

        ㆍ즉, 프로그래머가 boxing / unboxing 을 고려하지 않아도 되도록 Kotlin이 알아서 처리 해준다.

     

    3. Kotlin에서의 nullable 변수

    - kotlin에서 null이 변수에 들어갈 수 있다면 "타입?" 를 사용해야 한다.

    var number5: Long? = 1_000L
    number5 = null

     

    4. Kotlin에서의 객체 인스턴스화

    - Kotlin에서 객체 인스턴스화를 할 때에는 new를 붙이지 않아야 한다.

    val person = Person("박현민")

     

    정리

    - 모든 변수는 var / val을 붙여 주어야 한다.

        ㆍvar : 변경 가능하다 / val : 변경 불가능하다 (read-only)

    - 타입을 명시적으로 작성하지 않아도, 타입이 추론된다.

    - Primitive Type과 Reference Type을 구분하지 않아도 된다.

    - Null이 들어갈 수 있는 변수는 타입 뒤에 ? 를 붙여주어야 한다.

        ㆍ아예 다른 타입으로 간주된다.

    - 객체를 인스턴스화 할 때 new를 붙이지 않아야 한다.

     

    2. 코틀린에서 null을 다루는 방법

    1. Kotlin에서의 null 체크

    - Kotlin에서는 null이 가능한 타입을 완전히 다르게 취급한다! 

     

    2. Safe Call과 Elvis 연산자

    - null이 가능한 타입만을 위한 기능은 없나?!

     

    - Safe Call

        ㆍnull 이 아니면 실행하고, null이면 실행하지 않는다 ( 그대로 null )

    val str: String? = "ABC"
    str.length		// 불가능
    str?.length		// 가능

     

    - Elvis 연산자

        ㆍ앞의 연산 결과가 null이면 뒤의 값을 사용

    val str: String? = "ABC"
    str?.length ?: 0

     - Elvis 연산은 early return엗 사용할 수 있다!

    // java
    public long calculate(Long number) {
        if(number == null) {
            return 0;
        }
        
        // 다음 로직
    }
    
    
    // kotlin
    fun calculate(number: Long?): Long {
        number ?: return 0
        // 다음 로직
    }

     

    3. 널 아님 단언!!

    - nullable type이지만, 아무리 생각해도 null이 될 수 없는 경우

    fun startsWithA1(str: String?): Boolean {
        return str!!.startsWith("A")
    }

    - 혹시나 null이 들어오면 NPE가 나오기 떄문에 정말 null이 아닌게 확실한 경우에만 널 아님 단언!! 을 사용해야 한다.

     

    4. 플랫폼 타입

    - Kotlin에서 Java 코드를 가져다 사용할 때 어떻게 처리할까?!

        ㆍjavax.annotation 패키지

        ㆍandroid.support.annotation 패키지

        ㆍorg.jetbrains.annotation 패키지

    - @Nullable이 없다면?!!

        ㆍKotlin에서는 이 값이 nullable인지 non-nullable인지 알 수가 없다

     

    - 플랫폼 타입

        ㆍ코틀린이 null 관련 정보를 알 수 없는 타입 Runtime 시 Exception이 날 수 있다.

     

    * 코틀린에서 자바 코드를 사용할 때는 null 관련 정보를 꼼꼼히 작성하고, 라이브러리의 경우도 null값이 들어갈 수 있는지 없는 지 확인할 것

    * 최초에 코틀린에서 자바 라이브러리를 가져다 쓴 지점을 랩핑해서 단일 지점으로 만듦으로써 추후에 뭔가 이슈가 났을 때 좀 더 쉽게 대응할 수 있게 하면 좋다.

     

    정리

    - 코틀린에서 null이 들어갈 수 있는 타입은 완전히 다르게 간주된다.

        ㆍ한 번 null 검사를 하면 non-null임을 컴파일러가 알 수 있다.

    - null이 아닌 경우에만 호출되는 Safe Call (?.) 이 있다.

    - null인 경우에만 호출되는 Elvis 연산자(?:) 가 있다.

    - null이 절대 아닐때 사용할 수 있는 널 아님 단언(!!) 이 있다.

    - Kotlin에서 Java 코드를 사용할 때는 플랫폼 타입 사용에 유의해야 한다.

        ㆍJava 코드를 읽으면 널 가능성 확인 / Kotlin으로 Wrapping

     

    3. 코틀린에서 Type을 다루는 방법

    1. 기본 타입

    - Byte, Short, Int, Long, Float, Double, 부호없는 정수들

    - 코틀린에서는 선언된 기본값을 보고 타입을 추론한다.

    - Java와 다른 내용

        ㆍJava : 기본 타입간의 변환은 암시적으로 이루어질 수 있다.

    int number1 = 4;
    long number2 = number1;
    
    System.out.println(number1 + number2);

        ㆍKotlin : 기본 타입간의 변화은 명시적으로 이루어져야 한다.

    val number1 = 4
    // val number2: Long = number1	//Type mismatch
    val number2: Long = number1.toLong()
    
    println(number1 + number2)

     

    - kotlin에서 타입 변환 시 to변환타입() 을 사용해야 한다.

    - 변수가 nullable이라면 적절한 처리가 필요하다!

    val number3: Int? = 3
    val number4: Long = number3?.toLong() ?: 0L

     

    2. 타입 캐스팅

    - 기본 타입이 아닌 일반 타입은 어떨까?

    fun printAgeIfPerson(obj: Any) {
        if(obj is Person) {
            println(obj.age)    // 스마트 캐스트
    //        val person = obj as Person
    //        println(person.age)
        }
    }

     

    - value is Type

        ㆍvalue가 Type이면 → true

        ㆍvalue가 Type이 아니면 → false

    - value !is Type

        ㆍvalue가 Type이면 → false

        ㆍvalue가 Type이 아니면 → ture

     

    - value as Type

        ㆍvalue가 Type 이면 → Type으로 타입 캐스팅

        ㆍvalue가 Type이 아니면 → 예외발생(ClassCastException)

    - value as? type

        ㆍvalue가 Type 이면 → Type으로 캐스팅

        ㆍvalue가 null이면 → null

        ㆍvalue가 Type 아니면 → null

     

    3. Kotlin의 3가지 특이한 타입

    - Any

        ㆍJava의 Object 역할. (모든 객체의 최상위 타입)

        ㆍ모든 Primitive Type의 최상의 타입도 Any이다.

        ㆍAny 자체로는 null을 포함할 수 없어 null을 포함하고 싶다면, Any?로 표현.

        ㆍAny 에 equals / hashCode / toString 존재

     

    - Unit

        ㆍUnit은 Java의 void와 동일한 역할

        ㆍ(살짝 어려운 내용) void와 다르게 Unit은 그 자체로 타입 인자로 사용 가능하다

        ㆍ함수형 프로그래밍에서 Unit 은 단 하나의 인스턴스만 갖는 타입을 의미.

            즉, 코틀린의 Unit은 실제 존재하는 타입이라는 것을 표현

     

    - Nothing

        ㆍNothing은 함수가 정상적으로 끝나지 않았다는 사실을 표현하는 역할

        ㆍ무조건 예외를 반환하는 함수 / 무한 루프 함수 등

    fun fail(message: String): Nothing {
        throw IllegalArgumentException(message)
    }

     

    4. Stirng Interpolation, String indexing

    // java1
    Person person = new Person("박현민", 27);
    String log = String.format("사람의 이름은 %s이고 나이는 %s세 입니다", person.getName(), person.getAge());
    
    // java2
    StringBuilder builder = new StringBuilder();
    builder.append("사람의 이름은");
    builder.append(person.getName());
    builder.append("이고 나이는");
    builder.append(person.getAge());
    buidler.append("세 입니다");
    val person = Person("박현민", 27)
    val log = "사람의 이름은 ${person.name}이고 나이는 ${person.age}세 입니다"

    - ${변수} 를 사용하면 값이 들어간다.

     

    - TIP

        ㆍ변수 이름만 사용하더라도 ${변수}를 사용하는 것이 1) 가독성 2) 일관 변환 3) 정규식 활용 측면에서 좋았다.

        ㆍ코틀린 공식 코딩 컨벤선은 $변수 사용

     

    val str = """
        ABC        
    
    """.trimIndent()
    println(str)
    val str2 = "ABCDE"
    val ch = str[1]

     

    정리

    - 코틀린의 변수는 초기값을 보고 타입을 추론하며, 기본 타입들 간의 변환은 명시적으로 이루어진다.

    - 코틀린에서는 is, !is, as, as? 를 이용해 타입을 확인하고 캐스팅한다.

    - 코틀린에서 Any는 Java의 Object와 같은 최상위 타입이다.

    - 코틀린의 Unit은 Java의 void와 동일하다

    - 코틀린에 있는 Nothing은 정상적으로 끝나지 않은 함수의 반환을 의미한다.

    - 문자열을 가공할 때 ${변수}와 """ """ 를 사용하면 깔끔한 코딩이 가능하다.

    - 문자열에서 문자를 가져올때의 Java의 배열처럼 []를 사용한다.

     

    4. 코틀린에서 연산자를 다루는 방법

    1. 단항 연산자 / 산술 연산자

    - 단항 연산자 : ++ , --

    - 산술 연산자 : +, -, *, /, %

    - 산술대입 연산자 : +=, -=, *=, /=, %=

        → 자바, 코틀린 완전 동일

     

    - 비교 연산자 : >, <, >=, <=

        → Java, Kotlin 사용법은 동일하다.

            단, Java와 다르게 객체를 비교할 때 비교 연산자를 사용하면 자동으로 compareTo를 호출해준다.

     

    2. 비교 연산자와 동등성, 동일성

    - 동등성(Equality) : 두 객체의 값이 같은가?!

    - 동일성(Identity) : 완전히 동일한 객체인가?! 즉 주소가 같은가?!

     

    - Java 에서는 동일성에 == 를 사용, 동등성에 equals를 직접 호출

    - Kotlin에서는 동일성에 === 를 사용, 동등성에 ==를 호출

        ㆍ==를 사용하면 간접적으로 equals를 호출해준다.

     

    3. 논리 연산자 / 코틀린에 있는 특이한 연산자

    - 논리 연산자 : &&, ||, !

        → Java와 완전히 동일하다. Java처럼 Lazy 연산을 수행한다.

    if (fun1() || fun2()) {
        println("본문")
    }

    - fun1()이 true 이면 fun2()는 실행 X → Lazy 연산

     

    - in / !in

        ㆍ컬렉션이나 범위에 포함되어 있다, 포함되어 있지 않다.

    println(1 in numbers)

     

    - a..b

        ㆍa부터 b까지의 범위 객체를 생성한다.

     

    - a[i]

        ㆍa에서 특정 Index i로 값을 가져온다

    val str = "ABC"
    println(str[2])	//C

     

    - a[i] = b

        ㆍa의 특정 index i에 b를 넣는다.

     

    4. 연산자 오버로딩

    - Kotlin에서는 객체마다 연산자를 직접 정의할 수 있다.

    val money3 = Money(1_000L)
    val money4 = Money(2_000L)
    println(money3 + money4)    // Money(amount=3000)

     

    정리

    - 단항연산자, 산술연산자, 산술대입연산자 Java와 똑같다

    - 비교 연산자 사용법도 Java와 똑같다

        ㆍ단, 객체끼리도 자동 호출되는 compareTo를 이용해 비교 연산자를 사용할 수 있다.

    - in, !in / a..b / a[i] / a[i] = b 와 같이 코틀린에서 새로 생긴 연산자도 있다.

    - 객체끼리의 연산자를 직접 정의할 수 있다. 

     

     

    댓글

Designed by Tistory.