일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 배열
- 티스토리
- 연산자
- 알고리즘
- Windows
- Desktop
- 지식나눔강좌
- Programming
- c
- c++
- Direct2D
- 프로그래밍
- 백준
- 포인터
- 함수
- Tips프로그래밍강좌
- 김성엽
- Win32
- 이지스퍼블리싱
- Kotlin
- c#
- tipssoft
- VS ERROR
- Javascript
- 리뷰
- Visual Studio
- 문법
- Tips강좌
- CS
- doit코틀린프로그래밍
- Yesterday
- Today
- Total
F.R.I.D.A.Y.
Kotlin: 04 자료의 비교와 변환 본문

이번 시간에는 자료를 비교하고 특정 자료형을 다른 자료형을 변환하는 방법을 알아봅니다.
# 처음 프로그래밍을 접하는 분들께는 생소하고 어려울 수 있습니다.
Index
- 알아두기
- 데이터 저장/관리 방법
- 일반 변수
- 참조 변수
- 코틀린의 저장/관리 방식
- 데이터 저장/관리 방법
- 비교하기
- 이중 등호(==)
- 삼중 등호(===)
- 주의할 점
- 값의 변환(캐스팅)
- 암시적 형 변환
- 형 변환 메서드
- 스마트 캐스트
- 상위 자료형 이용하기
- is를 이용한 자료형 검사
- as에 의한 스마트 캐스트
- Next.
알아두기copy^
이 포스트를 이해하기 위해서는 한 가지 짚고 넘어가야 할 것이 있습니다. 코틀린의 데이터 저장/관리 방법입니다.
데이터 저장/관리 방법copy^
대개 프로그래밍 언어에서는 두 가지 방식의 변수를 제공합니다. 일반 변수와 참조 변수가 그것입니다.
일반 변수copy^
일반 변수는 데이터를 저장한 공간을 직접 가리키는 변수입니다. 마치 사람마다 고유한 이름이 있는 것처럼 말이죠.
참조 변수copy^
데이터를 특정 공간에 저장하면, 그 저장된 공간을 가리키는 변수라고 볼 수 있습니다. 대표적으로 C++에서는 참조 변수를 아래와 같이 작성합니다.
int value = 130; // 일반 변수
int& refValue = value; // 참조 변수
value라는 공간을 가리키는 refValue라는 변수가 생성되었습니다.
코틀린의 저장/관리 방식copy^
코틀린의 경우에는 모든 변수가 참조 변수의 성격을 가집니다. 코드상에서는 모두 참조 변수의 성격을 가지지만, 컴파일러 최적화를 거쳐 일부는 일반 변수처럼 사용됩니다.
fun main(args:Array<String>){
var num1 = 130
var num2 = 130
println("num1:$num1, num2:$num2")
num2 = 140
println("num1:$num1, num2:$num2")
}
이 코드를 예시로 들어보겠습니다. 변수 num1과 num2는 아래와 같이 데이터를 가리킵니다.

코틀린은 코드에 적힌 값들을 데이터 테이블[1]에 저장합니다.
num2 = 140
해당 코드가 실행되면 num2가 아래처럼 140이 저장된 공간을 가리키도록 변경됩니다.

비교하기copy^
fun main(args: Array<String>){
val str1:String = "Hello world"
val str2:String = "Hello world"
println(str1 == str2)
println(str1 === str2)
}
코틀린에서는 같은지를 판별하는 두 가지의 연산자가 존재합니다. 등호를 두 개 작성한 이중 등호와 세 개 작성한 삼중 등호입니다. 이 두 연산자 모두 값을 비교한다는 것에서는 같지만 그 쓰임이 다릅니다.
이중 등호(==)copy^
이중 등호는 일반적인 같음을 판단할 때 사용하는 연산자입니다. 단순히 숫자, 혹은 문자열을 비교할 때 사용할 수 있죠.
문자열 1 | 문자열 2 | 비교 결과 |
'Hello world!' | 'Hello world!' | true |
'Bye, world!'[# C언어의 창시자 데니스 리치가 사망할 때 그를 애도하는 의미에서 사용한 글귀입니다. 언어의 시작을 Hello world로 시작했기에 그의 마지막을 비슷한 방식으로 장식한 것이죠.] | 'bye, world!' | false[# 대소문자도 구별합니다.] |
삼중 등호(===)copy^
삼중 등호는 비교하는 값이 어디에 저장되어 있는지를 비교[2]합니다. 삼중 등호를 설명하기 위해서는 이후에 나올 세이프콜이 나와야 합니다. 지금은 "세이프콜이란 문법도 존재하는구나" 하고 가볍게 알아두기만 하기 바랍니다.
fun main(args:Array<String>){
val a:Int = 130
val b:Int = 130
println(a === b)
val c:Int? = a // 세이프콜
val d:Int? = a // 세이프콜
val e:Int? = c // 세이프콜
println(c == d)
println(c === d)
println(c === e)
}
이러한 코드가 있다고 생각해봅니다. 이 코드에서 다섯 개의 변수 a-e는 아래와 같이 값을 관리합니다.

세이프콜 변수는 기본적으로 참조형 변수로 가집니다. 그래서 c-e 변수는 힙을 가리키도록 하고 힙 메모리 공간에 실제 데이터를 저장하죠. 그러나 변수 e의 경우에는 c 변수를 값으로 가집니다. 힙에는 이미 c가 가리키는 곳이 존재하므로 변수 e는 힙에 공간을 새로 만들지 않고 c 변수가 가리키는 곳을 가리키게 됩니다. 이를 C언어로 이해하면 아래와 같습니다. 물론 C언어의 특성과 코틀린의 특성은 다르기 때문에 완전히 같다고 말할 수는 없을 것입니다. 그러나 C언어를 배웠다면[3] 이해하는데 도움이 될 것입니다.
// C 언어
int a = 130;
int b = 130;
printf("%d\n", a == b);
int *c = &a;
int *d = &a;
int *e = c;
printf("%d %d %d\n", *c == *d,
c == d, // c와 d를 삼중 등호로 비교하는 코드. 주소를 비교
e == c); // c와 e를 삼중 등호로 비교하는 코드. 주소를 비교
주의할 점copy^
비교하는 값이 만일 -128 ~ 127[4]이라면 삼중 등호를 이용해 비교하는 것이 제한됩니다. 1바이트로 표현 가능한 데이터는 캐시에 저장되어 위에서 비교한 코틀린 코드의 결과가 모두 참[5]으로 나타납니다.
값의 변환(캐스팅)copy^
특정 값을 잠시 다른 자료형으로 변경하는 캐스팅 문법입니다. 코틀린에서 정수를 표현할 수 있는 자료형은 한 가지가 아니었습니다. 코틀린에서 값을 비교할 때는 자료형이 다르면 비교 연산자를 사용할 수 없습니다. 그래서 우리는 값의 변환에 대해 알아야 합니다.
암시적 형 변환copy^
다른 프로그래밍 언어를 보면 암시적 형 변환이라 불리는 것이 있습니다. 아래 C언어를 보겠습니다.
short num1 = 130;
int num2 = num1;
num1의 값을 num2에 대입하려고 합니다. 자료형이 다르지만 컴파일에는 문제가 없습니다. 컴파일러가 형 변환을 해주기 때문입니다. 이를 암시적 형 변환이라고 합니다.
이런 식의 암시적 형 변환이 코틀린에서는 제공되지 않습니다.
val num1:Int = 130
val num2:Long = num1 // ERROR: num1(Int)의 자료형이 num2(Long)의 자료형과 다릅니다.
위와 같이 코드를 작성하면 두 번째 줄에서 오류를 터트리고 컴파일이 되지 않습니다. 그렇다면 코틀린에서는 어떻게 형 변환을 해야 할까요?
형 변환 메서드copy^
코틀린에서는 형 변환 연산자를 제공하지 않는 대신, 형 변환 메서드를 제공합니다.
메서드 명 | 설명 | 메서드 명 | 설명 |
toByte | Byte 타입으로 변환 | toFloat | Float 타입으로 변환 |
toShort | Short 타입으로 변환 | toDouble | Double 타입으로 변환 |
toInt | Int 타입으로 변환 | toChar | Char 타입으로 변환 |
toLong | Long 타입으로 변환 |
사용 방법은 아래와 같습니다.
fun main(args: Array<String>){
val a:Int = 20
println("${a.toLong()}")
}
예를 들어 코드와 같이 toLong()을 이용하면 Int 자료형의 변수 a 이더라도, 출력할 당시의 a 값의 자료형은 Long입니다.
스마트 캐스트copy^
컴파일러가 개발자 대신 형 변환을 해주는 기능을 스마트 캐스트라고 부릅니다.
상위 자료형 이용하기copy^
코틀린에서는 각 자료형을 포함하는 상위 자료형이 있습니다. 마치 부모가 자식을 끌어안는 것처럼 말이죠.
자료형 | 설명 |
Any | 모든 자료형의 부모(superclass) |
Number | Int, Long, Float 등 숫자형 자료형의 부모 |
이들을 이용하면 굳이 형 변환을 하지 않더라도 필요한 값을 넣고 출력할 수 있습니다.
fun main(){
var num:Number = 10
println("num type is ${num.javaClass}")
num = 10L
println("num type is ${num.javaClass}")
}
기존의 Int, Long 연산자를 사용했다면 컴파일 불가능했을 코드이지만, Number 자료형을 이용하니 가능합니다.
is를 이용한 자료형 검사copy^
코틀린에는 is 키워드 또한 존재합니다. 이 키워드는 각 자료형이 무엇인지 파악할 때 사용합니다. 또한 자료형을 is로 검사하게 되면, 해당 자료형을 변환하는 기능이 존재합니다.
is 키워드는 주로 Any 자료형과 함께 사용합니다.
fun main(args: Array<String>){
var tmp:Any = "Hello"
if(tmp is Int) println("$tmp")
else println("not Int")
}
위 코드를 설명하면 변수 tmp의 자료형이 Int로 변경될 수 있으면[if-else] tmp는 자료형이 Int로 캐스팅됩니다. 그러나 위 코드의 경우 Int로 변경할 수 없으므로 not Int가 출력됩니다.
만일 Int가 아닐 때 True를 출력하려면 is 앞에 부정 논리 연산자인 "!"를 붙여주면 됩니다.
fun main(args: Array<String>){
var tmp:Any = "Hello"
if(tmp !is Int) println("not Int")
else println("tmp is type of Int")
}
as에 의한 스마트 캐스트copy^
as라는 키워드도 존재합니다. is 키워드와 비슷하지만, 변경 불가시 오류를 출력하지 않는 is와는 달리 as 키워드는 오류를 출력합니다.
이후에 읽을 포스트에서 이 포스트에서 배운 내용이 보강될 것입니다. 소개되지 않는 문법을 이용해 설명하는 것을 최대한 배제하려고 하다 보니 같은 내용을 여러 포스트에 걸쳐 보강하고 보강하는 방식으로 글이 써지겠네요.
Next.copy^
Kotlin: 05 연산자
이전 포스트들에서 몇 가지 연산자들을 먼저 사용해 보았습니다. 이번 시간에는 먼저 사용한 연산자들을 포함해 어떤 연산자들이 있고 그 기능은 무엇인지 알아봅니다. 산술 연산자 수학에서 산술 연산자라 하면..
pang2h.tistory.com
'DEV > Kotlin' 카테고리의 다른 글
Kotlin: 06 세이프콜과 non-null 단정 (0) | 2020.03.29 |
---|---|
Kotlin: 05 연산자 (0) | 2020.03.28 |
Kotlin: 03 출력하기 (0) | 2020.03.24 |
Kotlin: 02 변수와 자료형 (1) | 2020.03.23 |
Kotlin: 01 시작하기 (2) | 2020.03.22 |