목차
개요
Java에서는 자료형이 원시형(Primitive Type)과 참조형(Reference Type)으로 나뉜다. 원시형이란 int
, long
, double
등과 같이 실제 자료값만을 저장하는 타입이고, 참조형은 객체를 생성하고 메모리 영역에 값을 저장한 후 메모리 주소를 통해 값을 참조하는 타입으로, 원시형을 제외한 나머지 타입(배열, 열거형, 각종 클래스의 객체 등)이 포함된다. 원시 자료형의 Wrapper Class인 Integer
, Long
, Double
등 또한 모두 참조형에 속한다.
Kotlin의 자료형에는 원시형이 존재하지 않고 모든 자료형이 참조형이다. 다르게 말하면, 모든 자료형은 클래스이고 모든 변수는 객체가 된다는 뜻이다. 이 때문에 모든 자료형의 첫 글자가 대문자로 작성된다. 또한, Java에서는 원시 자료형에 별도의 메소드를 사용하거나 Collection 객체에 원시 자료형을 추가하려면 별도로 Wrapper Class를 사용해야 했던 것과는 달리 자료형을 그대로 사용할 수 있다.
이번 포스팅에서는 정수, 실수, 논리, 문자, 문자열 자료형에 대해 정리하고자 한다.
정수 자료형
Kotlin도 Java와 마찬가지로 정수 자료형에는 Byte
, Short
, Int
, Long
이 존재한다. 각 자료형의 크기와 값의 범위는 다음 표와 같다. 이 중 Long
타입의 경우에는 값을 변경할 때 숫자 뒤에 반드시 L을 붙여줘야 한다.
타입 | 크기 | 최소값 | 최대값 |
Byte |
1Bytes(8bits) | -128(-27) | 127(27-1) |
Short |
2Bytes(16bits) | -32,768(-215) | 32,767(215-1) |
Int |
4Bytes(32bits) | -2,147,483,648(-231) | 2,147,483,647(231-1) |
Long |
8Bytes(64bits) | -9,223,372,036,854,775,808(-263) | 9,223,372,036,854,775,807(263-1) |
var a: Long = 123 // 컴파일 에러
var b: Long = 123L // OK
Kotlin에서는 정수 자료형에 한해서 Java에서 제공하지 않는 Unsigned
자료형도 제공한다. 이 경우 각 자료형의 앞에 U가 붙은 UByte
, UShort
, UInt
, ULong
로 사용할 수 있다. Unsigned
자료형의 범위는 아래와 같다. Unsigned
로 선언된 변수를 변경하고 싶다면 숫자 뒤에 반드시 u를 붙여야 한다.
타입 | 크기 | 최소값 | 최대값 |
UByte |
1Bytes(8bits) | 0 | 255(28-1) |
UShort |
2Bytes(16bits) | 0 | 65,535(216-1) |
UInt |
4Bytes(32bits) | 0 | 4,294,967,295(232-1) |
ULong |
8Bytes(64bits) | 0 | 18,446,744,073,709,551,615(264-1) |
var a: UInt = 123 // 컴파일 에러
var b: UInt = 123u // OK
Kotlin은 Java와 마찬가지로 정수값을 대입할 때 리터럴의 맨 앞에 0x를 붙여 16진수를, 0b를 붙여 2진수를 대입할 수 있으며, 언더스코어(_)를 이용하여 자리값을 구분할 수도 있다.
val a = 123_456 // 123456
val b = 1_23_4_5_6 // 언더스코어는 숫자 사이 아무 위치에나 추가할 수 있음
val c = 0xff // 255
val d = 0b1111 // 15
실수 자료형
Kotlin도 Java처럼 Float
과 Double
을 실수 자료형으로 사용한다. 이 두 유형은 아래의 표와 같이 서로 다른 정밀도와 크기, 소수점 이하 자릿수를 가진다. Java와 마찬가지로 Float 타입은 숫자 맨 끝에 f를 붙여야 한다. 소수점 이하의 수가 지수부의 범위를 초과하게 되면 초과한 부분은 버려진다.
타입 | 크기 | 가수부 | 지수부 | 소수점 이하 자릿수 |
Float |
4Bytes(32bits) | 24 | 8 | 6~7 |
Double |
8Bytes(64bits) | 53 | 11 | 15~16 |
val a = 1.23 // Double
val b = 4.56f // Float
val c = 0.987654321987654321 // 0.9876543219876543
val d = 0.987654321987654321f // 0.9876543
논리 자료형
논리 자료형은 Java와 마찬가지로 Boolean
만 존재하며 true와 false만을 값으로 가질 수 있다. 주로 조건을 검사할 때 사용한다.
val a = 5 % 2
val isOdd = a == 1 // true
val isEven = a == 0 // false
문자 자료형
문자 자료형은 Java와 마찬가지로 Char
를 사용한다. Char
는 2바이트의 크기를 가지며, 'a'
와 같이 리터럴을 작은 따옴표로 감싸서 한 글자를 표현한다. 문자.code
를 사용하면 해당 문자의 유니코드 값을 10진수로 얻을 수 있다. 만약 작은 따옴표를 문자형 변수에 집어넣고 싶다면 작은따옴표 앞에 역슬래시(\)를 붙여주면 된다. 또한, 역슬래시 뒤에 u와 함께 4자리 16진수 형태의 유니코드 값을 집어넣는 것으로 그 값에 해당하는 문자를 표현할 수도 있다.
val a = '가'
val b = '\''
val c = '\uac00'
println(a) // 가
println(a.code) // 44032
println(b) // '
println(c) // 가
Java에서는 char
타입에 정수를 저장하면 자동으로 그 값에 해당하는 문자가 되었으나 Kotlin에서는 이러한 방식이 불가능하다. Kotlin의 Char
타입에 정수 값에 해당하는 문자를 저장하고 싶다면 정수.toChar()
메소드를 사용하여 문자형으로 변환하거나 상기했듯이 '\u(4자리의 16진수)'
의 형태로 작성해야 한다.
val a: Char = 97 // 컴파일 에러
val b = 97.toChar() // a
val c = '\u0061' // a
문자열
문자열은 Java와 마찬가지로 String
을 사용하며, 큰 따옴표(")로 감싸서 여러 문자를 표현한다. 또한, 큰 따옴표 3개로 리터럴을 감싸면 HTML의 <pre>
태그처럼 개행과 공백을 모두 포함하여 문자열을 저장할 수 있다. Java에서는 \n
와 +
를 사용해서 줄을 바꿔가며 입력해야 했던 것에 비하면 상당히 편리하다고 볼 수 있다. 이외에도 Kotlin의 String
클래스는 Java와 다른점이 좀 있기 때문에 이 부분에 대해서는 다음 포스트에서 더 자세히 정리하고자 한다.
// Java
String str1 = "Hello World";
String str2 = "Hello World!\n"
+ "This is Test String.\n"
+ "Colabear754";
// Kotlin
val str1 = "Hello World"
val str2 = """
Hello World!
This is Test String.
Colabear754.
"""
println(str1) // Hello World
println(str2)
/*
Hello World!
This is Test String.
Colabear754.
*/
"""
를 사용하면 코드의 가독성을 높이기 위한 들여쓰기 공백까지 함께 저장하게 되는데 이 경우 저장할 문자열 각 줄의 맨 앞에 파이프 문자(|)를 붙이고 trimMargin()
를 사용하면 |
앞의 공백을 제거해 주므로 들여쓰기로 코드의 가독성을 높이면서 문자열에는 들여쓰기 공백을 제거하여 저장할 수 있다. 만약 파이프 문자 대신 다른 문자로 줄의 시작 부분을 표시하고 싶다면 해당 문자를 trimMargin()
메소드의 파라미터로 보내면 된다.
val str1 = """
Hello World!
This is Test String.
Colabear754.
"""
println(str1)
/*
Hello World!
This is Test String.
Colabear754.
*/
val str2 = """|
|Hello World!
|This is Test String.
|Colabear754.
""".trimMargin()
println(str2)
/*
Hello World!
This is Test String.
Colabear754.
*/
val str3 = """
@Hello World!
@This is Test String.
@Colabear754.
""".trimMargin("@")
println(str3)
/*
Hello World!
This is Test String.
Colabear754.
*/
Kotlin의 null-safe 특성
Kotlin의 모든 자료형은 기본적으로 null 값을 허용하지 않아 null이 발생하게 될 경우 컴파일 시점에 미리 알려줘서 런타임에 예상치 못한 NullPointerException이 발생하는 것을 방지할 수 있다. 만약 null을 사용하고 싶다면, 클래스나 자료형의 이름 뒤에 물음표(?)를 붙여서 nullable한 객체라는 것을 명시해줘야 한다.
val a: Int = null // 컴파일 에러
val b: Int? = null // OK
Java의 원시형에 해당하는 자료형의 경우엔 이 nullable 부분이 조금 다르게 동작하는데, non-null 타입일 경우에는 원시형으로 변환되지만 nullable 타입일 경우에는 Wrapper Class로 변환된다. 위의 코드를 Java로 변환하면 아래와 같아진다.
int a = null; // 컴파일 에러
Integer b = null; // OK
Kotlin에서는 nullable한 객체와 non-null인 객체는 서로 다른 자료형으로 취급한다. 그렇기 때문에 non-null인 객체에 nullable한 객체를 대입하려고 시도하면 컴파일 에러가 발생한다.
var a = 123
var b: Int? = 456
a = b // 컴파일 에러
하지만 방법이 전혀 없는 것은 아니다. non-null인 객체에 대입하고자 하는 nullable한 객체 뒤에 느낌표를 2개 붙여주면 대입하고자 하는 값이 null이 아니라는 것을 보장해준다. 다만, 이 경우 실제 값이 null인 객체에 !!
를 붙여서 저장하려고 하면 NullPointerException이 발생하기 때문에 주의를 기울여서 사용해야 한다.
var a = 123
var b: Int? = 456
a = b!! // OK
var c = 789
var d: Int? = null
c = d!! // NullPointerException
다른 방법으로는 non-null인 객체에 대입하고자 하는 nullable한 객체 뒤에 물음표와 콜론(:)을 붙이는 방법도 있다. 이렇게 하면 대입하고자 하는 객체가 null일 경우에 콜론 뒤에 있는 값을 대신 대입한다.
var a: Int
val b = null
a = b ?: 123
println(a) // 123
nullable한 객체에는 제한 없이 non-null인 객체를 대입할 수 있다. non-null인 객체를 주입받은 nullable한 객체는 null을 다시 대입하지 않는 한, non-null인 객체처럼 사용할 수 있다.
var a = 10
var b: Int? = 20
var c = 30
b = c
a = b // nullable인 b에 non-null인 c를 저장하여 b의 non-null이 보장됨
b = null
c = b // b에 null을 저장하면서 non-null 보장성이 사라졌기 때문에 컴파일 에러 발생
마무리
Kotlin의 기본 자료형과 null-safe 특성에 대해 정리해보았다.
다음 포스트에서는 Kotlin의 String 클래스에 대해 조금 더 자세히 정리하고자 한다.
댓글 피드백은 언제나 환영합니다.
'Programming Language > Kotlin & Java' 카테고리의 다른 글
Kotlin 기본 문법 5 : 배열 (0) | 2022.11.25 |
---|---|
Kotlin 기본 문법 4 : 조건문과 반복문 (0) | 2022.11.23 |
Kotlin 기본 문법 3 : String (0) | 2022.11.21 |
Kotlin 기본 문법 1 : 개요 및 변수와 함수 (2) | 2022.11.18 |
Kotlin : 시작하기에 앞서 (0) | 2022.11.18 |
댓글