CODING/강의노트-부스트코스-코틀린

[부스트코스]📱코틀린 2-3 검사와 자료형을 변환해보기

codingTrip 2021. 1. 28. 18:10

안녕하세요? codingTrip입니다.

오늘은 "코틀린 프로그래밍  1/2(함수편)"

1단원 코틀린의 기본을 익혀요!

2장. 변수와 자료형, 연산자

2-3 검사와 자료형을 변환해보기

시작하겠습니다!

 

 

🧪 자료형 비교, 검사, 변환

▷ 코틀린의 자료형 변환

- 기본형을 사용하지 않고 참조형만 사용
- 서로 다른 자료형은 변환 과정을 거친 후 비교

코틀린은 기본형을 사용하지 않고, 참조형 자료형을 쓰고 있습니다.

서로 다른 자료형으로 변환하려면, 변환 메소드가 필요합니다.

그래서 바로 변환되지 않아요.

 

[출처] 부스트코스 코틀린 강의자료

첫 번째 줄에서 a라는 변수를 선언했고, 이것을 Int으로 정의하고, 1로 초기화했습니다.

두 번째 줄에서는 b라는 변수를 Double으로 지정했습니다.

즉, a와 b는 자료형이 다릅니다.

만약, Double형인 ba를 할당하려고 한다면, 문제가 발생합니다.

세 번째 줄에서 c라는 변수 선언하고, Int1.1 실수형태으로 초기화한다면, 불일치로 오류가 발생합니다.

결국, 둘 다 자료형 불일치오류가 발생합니다.

 

- 변환 메서드의 이용

[출처] 부스트코스 코틀린 강의자료

이렇게 오류가 발생하는 상황에서 우리가 할 수 있는 방법은 다음과 같습니다.

b라는 Double형의 변수를 선언하고 a.toDouble()변환 메서드를 사용합니다.

이렇게 하면 a가 b에 할당될 수 있습니다.

변환메서드의 종류는 많기 때문에 나중에 살펴보겠습니다.

 

- 표현식에서 자료형의 자동 변환

[출처] 부스트코스 코틀린 강의자료

연산 수식을 사용할 때

위의 식에서는 자료형을 특정하지 않고 추론하게 했으므로

1뒤에 L을 붙여서 Long입니다

LongInt형의 연산은 일단 큰 자료형인 Long형으로 변환됩니다.

즉, 변수 resultLong이 됩니다.

 

▷ 변환 메서드의 종류

  • toByte: Byte
  • toLong: Long
  • toShort: Short
  • toFloat: Float
  • toInt: Int
  • toDouble: Double
  • toChar: Char

👓 기본형과 참조형 자료형의 비교 원리

▷ 이중 등호(==)와 삼중 등호(===)의 사용

== 값만 비교하는 경우
=== 값과 참조 주소를 비교할 때

값만 비교하려면 ==을 사용하고,

참조 주소까지 비교하려면 ===을 사용해야 합니다.

(자바에서는 ==로 값과 참조 주소를 비교하므로 주의하세요!)

두 연산자가 다르기 때문에 꼭! 주의 하시기 바랍니다.

[출처] 부스트코스 코틀린 강의자료

변수 a와 b를 값만 비교했을 경우에는 true로 나오고,

참조 주소까지 비교했을 경우에도 true로 나옵니다.

이 경우에는 128이라는 이 수치 값 자체가 해당 스택에 쌓여있기 때문에

참조 주소 자체가 128이기 때문에 주소도 같습니다.

 

▷ 참조 주소가 달라지는 경우

[출처] 부스트코스 코틀린 강의자료

a, b는 128라는 같은 값을 갖고 있지만

변수 b는 null이 가능한 정수형으로 선언했으므로(Int?) 참조주소가 서로 달라집니다.

a는 컴파일 상으로 기본형으로 들어갑니다. 스택에 들어가고

b기본형이 아닌 객체가 되어 특정 힙 동적 공간에 들어갑니다.

b라는 변수를 가리키는 스택에는 일종의 참조주소가 담겨져 있죠.

따라서, 서로 다른 참조주소를 가지기 때문에  a===bfalse입니다.

 

💻 코딩해 보세요!

▷이중 등호 비교와 삼중 등호 비교하기

section03폴더Alt+Insert누르고 Kotlin File을 만듭니다.

 

파일명은 ValRefCompare로 합니다.

 

package chap02.section03

fun main() {
    val a: Int = 128
    val b=a
}

변수 b의 경우에는 자료형을 추론해야 하기 때문에

그 줄을 블록 잡고, Ctrl+Shift+P를 누르면

Int형이라고 추론이 됩니다.

 

package chap02.section03

fun main() {
    val a: Int = 128
    val b: Double =a
}

이렇게 Double형으로 선언하는 경우

자료형 불일치 오류가 발생합니다.

 

package chap02.section03

fun main() {
    val a: Int = 128
    val b: Double =a.toDouble()
}

이렇게 오류가 난 경우에, 변환 메서드를 사용해서

val b: Double =a.toDouble()로 변환한다고 이야기 했었죠?

 

package chap02.section03

fun main() {
    val a: Int = 128
    val b = a
    println(a==b)
    println(a===b)
}

하지만 우리는 int형으로 추론되게끔 하기 위해서 b의 자료형 선언을 생략할 겁니다.

그럼 a==b로 먼저 값의 비교를 해볼까요?

실행 단축키 Shift+Alt+F10를 누르고,  2번을 클릭합니다.

 

결괏값이 true가 나오죠?

참조 주소의 비교true가 나옵니다.

 

package chap02.section03

fun main() {
    val a: Int = 128
    val b = a

    val c: Int? = a
    val d: Int? = a
    val e: Int? = c
    
    println(c==d)
    println(c===d)
    println(c===e)
}

먼저 변수 c와 d를 비교해보겠습니다.

값은 동일해서 true가 나왔지만 c와 d는 기본형이 아닌 객체가 되어서 동적공간에 존재하고,

c와 d에 들어있는 곳은 실제 스택에 특정 객체를 가리키는 주소가 됩니다.

128로 값이 같다고 할지라도 값만 같을 뿐 위치는 달라집니다.

그래서 false가 나옵니다.

 

다음으로 변수 c와 e를 비교해보겠습니다.

변수 c에서 동일하게 선언되어 있는 형태가

객체 참조형으로 되어있는 c로 선언이 되있고

e가 거기에 동일하게 c가 가리키고 있는 공간을 할당해서 가리키기 때문에

true가 나옵니다.

 

사실 저는 이렇게 말로 들으니 이해가 잘 안가더라고요. ㅠㅠ

이런 저의 마음을 선생님께서 아셨는지 그림으로 다시 설명해주셨습니다.

 

[출처] 부스트코스 코틀린 강의자료

그림으로 정리해보겠습니다.

변수 a,b는 기본형이므로 Stack에 존재하고 주소가 아닌 값입니다.

하지만 변수 c,d,e Int? 형태로 선언했으므로 참조형입니다.

변수 cHeap이라는 동적 공간에 생성해서 담아놓게 됩니다.

변수 d또 다른 공간에 담아놓습니다.

값은 동일하지만 주소가 달라지기 때문에 둘의 참조주소는 다릅니다.

하지만 변수 e변수 c를 통해서 할당하게 되어

주소가 동일해서 변수 e는 변수 c의 주소를 담는 것과 같습니다.

즉, 같은 공간을 가리키기 때문에 서로 동일한 공간, 값을 갖게 됩니다.

 

다시 정리하자면,

null이 불가능한 형태기본형

null 가능한 형태 참조형

꼭! 기억하세요!

 

참고

코틀린에서는 참조형으로 선언한 변수의 값이 –128~127 범위있으면 캐시에 그 값을 저장합니다.

즉, 특정 객체 공간에 할당하는 것 대신에 캐시에 담겨집니다.

캐시에 담겨진 경우에는 지정한 객체 생성 방식이 아니기 때문에

참조형에 대한 연산을 수행하면 다 같은 값이 나올 수 있습니다.

 

🔎 스마트 캐스트

▷구체적으로 명시되지 않은 자료형을 자동 변환

- 값에 따라 자료형을 결정
- Number형은 숫자를 저장하기 위한 특수한 자료형으로 스마트 캐스됨

만약 우리가 자료형을 선언하면 그 자료형으로 변수가 선언되어 만들어지죠?

하지만 자료형을 명시하지 않으면, 특정 자료형으로 자동변환해야 하는 경우가 생깁니다.

이럴 때는 대부분 컴파일러값에 따라 추론하고 있지만,

만약 특정 값이 어떤 값인지 몰라서 추론을 할 수 없는 경우에는

자료형을 명시해줘야 합니다.

그렇지 않으면 1은 정수형, 1.1은 실수형, 1L은 Long형 등의

우리가 특정 값을 정해줄 때, 규칙에 따라서 놓여주게 되면

컴파일러는 자동으로 결정하게 됩니다.

 

특정 자료형이 아닌 추상적인 자료형을 사용하는 경우에는

마음대로 바꿀 수 있습니다.

Number형Int, Long형 같은 다양한 수치를 가진 자료형을

상위로 가지는 자료형입니다.

Number형으로 선언하게 되면

하위의 어떤 숫자 타입으로도 변환할 수 있습니다.

 

💻 코딩해 보세요!

▷ 스마트 캐스트 사용해보기

사실 이 부분은 선생님께서 따로 같이 코딩실습하지 않으셨어요.

그래도 저는 해보겠습니다.

section03폴더Alt+Insert를 눌러 코틀린 파일을 만듭니다.

파일명SmartCast라고 임의로 지었습니다. (여러분은 다르게 지으셔도 돼요.)

 

package chap02.section03

fun main() {
    var test: Number = 12.2
    println("$test")

    test = 12
    println("$test")

    test = 120L
    println("$test")

    test = 12.0f
    println("$test")

    /*test = "Hello"
    println("$test")*/
    //주석처리를 풀고 직접 확인해보시기 바랍니다.
}

실행 단축키 Shift+Alt+F10를 누르고,  2번을 클릭합니다.

12.2는 사실 Float형이죠 그래서 Float형으로 스마트 캐스트가 됩니다.

12일 때는 Int형으로 스마트 캐스트가 됩니다.

120L일 때는 Long형으로 스마트 캐스트가 됩니다.

12.0f일 때는 Float형으로 스마트 캐스트가 됩니다.

이렇게 스마트 캐스트는 필요에 따라서 값을 바꿀 수 있는 형태가 됩니다.

 

다만 Number

예를 들어, test=“Hello”라고 값을 넣을 경우에는

"Hello"문자열형이고, 숫자 타입이 아니기 때문에 캐스트가 불가능합니다

 

💡 자료형의 검사

▷ is 키워드를 사용한 검사

[출처] 부스트코스 코틀린 강의자료

변수 num은 값이 256이므로 정수형으로 추론될 수 있죠.

검사를 하고 싶을 때는, num is형을 사용해서 Int인지 검사를 합니다.

if (num is Int){

만약, Int형이면 

  print(num)

num을 출력하고

}else if (num !is Int){

num이 Int형이 아닐 경우에는

  print("Not a Int")

}

Not a Int를 출력합니다.

이렇게 is 키워드를 사용해서 간단히 타입을 알 수 있습니다.

 

저는 또 간단하게 실습해보았습니다.

package chap02.section03

fun main() {
    val num = 256L

    if(num is Int){
        print(num)
    } else if(num !is Int){
            print("Not a Int")
        }
}

위의 사진처럼 변수 num의 자료형 Int형일 경우에는

이렇게 변수 num을 출력합니다.

 

그런데 이렇게 변수 num에 Int가 아닌 자료형을 넣었을 때,

print("Not a Int")을 할 줄 알았는데...

오류가 뜨네요... 혹시나해서 같은 숫자형인 Long형을 해도 오류가 나오더라고요.

컴파일상에서 Int가 아닌 것을 감지하나봐요.

 

📸 묵시적 변환

▷ Any

[출처] 부스트코스 코틀린 강의화면

자료형이 정해지지 않은 경우
모든 클래스의 뿌리 – Int나 String은 Any형의 자식 클래스이다.
Any는 언제든 필요한 자료형으로 자동 변환(스마트 캐스트)

Any형자료형이 정해지지 않은 경우입니다.

그래서 어떤 타입이라도 될 수 있는데요.

앞서 설명드렸던 Number라는 타입하부에는 Int, Long형 등의 숫자형 타입이 존재합니다.

 

이것을 다시 따라가보면 최상위에 Any타입이 있습니다.

모든 다양한 타입을 아우를 수 있습니다.

모든 클래스의 뿌리가 됩니다.

IntStringAny형의 자식 클래스입니다.

그렇기 때문에 Any형으로 선언한 경우에는

어떠한 형으로든 변환할 수 있겠죠?

스마트 캐스트가 가능하다는 이야기입니다.

 

 

💻 코딩해 보세요!

▷ Any형 변수의 반환

[출처] 부스트코스 코틀린 강의자료

Any타입으로 선언한 다음에 1로 초기화하면 정수형으로 스마트캐스트되고

20L으로 하면 Long형으로 스마트캐스트가 되고

“Hello”가 되어도 String형으로 스마트 캐스트가 될 수 있습니다.

a.javaClass를 하면 자바 기본형을 출력할 수 있습니다.

 

이것도 직접 실습해보았습니다.

package chap02.section03

fun main() {
    var a:Any = 1
    a = 20L
    a = "Hello"
    println("a: $a type: ${a.javaClass}")
}

이렇게 실습을 해보면 어떤 타입으로 값을 바꿔도 오류가 없음을 확인할 수 있습니다.

“Hello”가 되어도 String형으로 스마트 캐스트가 될 수 있습니다.

 

▷ Any형으로 인자를 받는 함수 만들기

[출처] 부스트코스 코틀린 강의자료

매개변수 xAny 타입으로 선언한 경우에는

어떤 타입으로도 선언할 수 있습니다.

만약 String일 경우에는 println("x is String: $x")을 하고

Int인 경우에는 println("x is Int: $x")을 합니다.

 

실습 이번에도 간단히 해보았습니다.

package chap02.section03

fun main() {
    checkArg("Hello")
    checkArg(5)
}

fun checkArg(x: Any){
    if (x is String){
        println("x is String: $x")
    }
    if (x is Int){
        println("x is Int: $x")
    }
}

매개변수 x Any 타입으로 선언한 경우에는 어떤 타입으로도 선언할 수 있다는 것이 확인 가능하죠?

 

 

 

 

자, 이렇게 오늘도 마무리가 되었네요.

사실 점점 새로운 개념이 나와서 힘들지만

그래도 차근히 실습하면서 파악하고 있어요.

선생님께서 직접 실습하지 않으시고

설명만 하고 지나가시는 부분도

꼭 한 번 실습해보세요!

예상치 못한 오류에 당황하기도 하고

어떻게 해결해야 하는지 검색도 하고

그런 고군분투가 점점 쌓여서

우리에게 재산이 될테니까요.

 

강의 중간중간에 자막으로 주의할 점 나오는 점이 좋았어요.

자막 앞에 오리? 그림이 나오는 게 귀여워서

자주 나오길 은근 기대하고 있어요. ㅋㅋㅋ

이번 강의에는 선생님께서 그림으로 설명해주신 점이 인상깊었답니다.

기본형, 참조형 부분이 이해가 안갔었는데

자료화면의 그림으로 다시 설명해 주셔서

이해가 더 쉬웠습니다.

그리고 Any형은 직접 그림을 그려주셔서 이해하기가 쉬웠답니다.

 

중간중간 아기 목소리 나서 저는 좋았어요.

강의에 열심히 집중하고 있는

저에게 주는 작은 상 같아요. ㅎㅅㅎ

 

그럼 다음 시간에 만나요.

 

 

부스트코스 서포터즈 3기 codingTrip