https://kotlinlang.org/docs/basic-types.html
Basic types | Kotlin
kotlinlang.org
- Basic types
코틀린에서도 모든 것은 객체이다.
호출하는 함수와 그 어떤 속성도 모두 객체이다.
Integer types
코틀린에서는 4가지의 숫자 타입을 제공한다.
Type | Size | Min Value | Max Value |
Byte | 8 | -128 | 127 |
Short | 16 | -32768 | 32767 |
Int | 32 | -2,147,483,648 (-231) | 2,147,483,647 (231 - 1) |
Long | 64 | -9,223,372,036,854,775,808 (-263) | 9,223,372,036,854,775,807 (263 - 1) |
만약 처음에 타입을 지정해주지 않는다면, 컴파일러는 자동으로 Int로 지정해주게 된다.
만약 Int의 범위 밖이라면, 타입은 Long으로 지정되게 된다.
처음에 Long 타입으로 지정해주고 싶다면, 숫자 뒤에 L을 붙여야 한다.
val a = 1 // Int
val b = 3030303030303030303030 //Long
val c = 123L // Long
Floating-point types
코틀린은 실수에 대해, Float와 Double을 제공한다.
Float은 Single precision, Double은 Double precision
Type | Size | Significant bits | Exponent bits | Decimal digits |
Float | 32 | 24 | 8 | 6-7 |
Double | 64 | 53 | 11 | 15-16 |
실수를 선언하면 자동으로 Double로 지정이되며, Float로 지정하고 싶다면 뒤에 f를 붙여주어야 한다.
val e = 2.7182818284 // Double
val eFloat = 2.7182818284f // Float, actual value is 2.7182817
Literal constants for numbers
수는 다음과 같이 표현할 수 있다.
- Decimals: 123
- Longs: 123L
- Hexadecimals: 0x0F
- Binaries: 0b00010101
- Doubles by default: 123.5, 123.5e10
Numbers representation on the JVM
자바에서는 수를 Int, double로 저장하게 된다.
하지만 이런 타입에는 null이 지정되지 못한다.
그러면 코틀린에서의 Int?는 어떻게 되는 것일까?
그런 경우에는 자바에서의 boxed type인 Integer, Double을 사용했었다.
nullable 타입은 같은 수라도 다른 object를 참조한다.
fun main() {
val a: Int = 100
val boxedA: Int? = a
val anotherBoxedA: Int? = a
val b: Int = 10000
val boxedB: Int? = b
val anotherBoxedB: Int? = b
println(boxedA === anotherBoxedA) // true
println(boxedB === anotherBoxedB) // false
}
이런 일이 생기는 이유는 ~128~127의 범위는 JVM이 메모리 최적화를 위해 같은 곳을 참조하도록 하기 때문이다.
하지만 b의 경우에는 그런 일이 생기지 않는다.
Explicit number conversions
다른 표현 방식 때문에, smaller type은 bigger의 subtype이 아니다.
따라서 아래와 같은 경우 문제가 발생한다.
// Hypothetical code, does not actually compile:
val a: Int? = 1 // A boxed Int (java.lang.Integer)
val b: Long? = a // Implicit conversion yields a boxed Long (java.lang.Long)
print(b == a) // Surprise! This prints "false" as Long's equals() checks whether the other is Long as well
그렇기 때문에 Smaller type은 bigger 타입으로 자동 캐스팅이 되지 않는다.
따라서 명시적인 변환을 거쳐야 한다.
val b: Byte = 1 // OK, literals are checked statically
// val i: Int = b // ERROR
val i1: Int = b.toInt()
Operations on numbers
코틀린은 +, -, *, /, %와 같은 기본 연산자를 지원한다.
Division of integers
Int 끼리의 나누기는 항상 Int를 반환한다.
소숫점 부분은 무시된다.
val x = 5 / 2
//println(x == 2.5) // ERROR: Operator '==' cannot be applied to 'Int' and 'Double'
println(x == 2)
소숫점까지 구하기 위해서는 하나를 명시적으로 float 타입으로 변환해주어야 한다.
val x = 5 / 2.toDouble()
println(x == 2.5)
- Unsigned integer types
Unsigned integer types
Integer type에 더해, 코틀린은 unsigned 값들을 제공한다.
Type | Size | Min value | Max value |
UByte | 8 | 0 | 255 |
UShort | 16 | 0 | 65,535 |
UInt | 32 | 0 | 4,294,967,295 |
ULong | 64 | 0 | 18,446,744,073,709,551,615 |
Unsigned arrays and ranges
다른 원시 타입들과 같이, 해당 데이터 타입들도 배열을 제공한다.
UByteArray: and array of unsigned bytes
UShortArray: an array of unsigned shorts
UIntArray: an array of unsigned ints
ULongArray: an array of unsigned longs
Unsigned integers literals
unsigned 타입을 더 명확하게 사용하기 위해, 코틀린은 해당 suffix를 제공한다.(Float, Long과 같이)
뒤에 u, U를 붙이면 해당 unsigned 타입으로 컴파일러가 인지하게 된다.
val b: UByte = 1u // UByte, expected type provided
val s: UShort = 1u // UShort, expected type provided
val l: ULong = 1u // ULong, expected type provided
val a1 = 42u // UInt: no expected type provided, constant fits in UInt
val a2 = 0xFFFF_FFFF_FFFFu // ULong: no expected type provided, constant doesn't fit in UInt
- Booleans
Boolean 타입은 true, false 이렇게 두가지만 가지는 boolean object이다.
다른 언어와 마찬가지로
|| : disjunction(Logical OR)
&&:: conjunction (Logical AND)
!: negation(Logical NOT)
val myTrue: Boolean = true
val myFalse: Boolean = false
val boolNull: Boolean? = null
println(myTrue || myFalse)
// true
println(myTrue && myFalse)
// false
println(!myTrue)
// false
println(boolNull)
// null
||, &&는 Lazy하게 동작하기도 한다.
무슨말이냐면, first operand가 true라면 OR는 second operand를 확인하지 않는다.
마찬가지로, first operand가 false라면 and는 second operand를 확인하지 않는다.
- Charaters
Character는 작은따옴표 안에 있는 문자 하나를 말한다. ex) '1'
backslash로 시작하는 Special Character가 존재한다.
아래와 같은 역할을 한다.
\t: tab
\b: backspace
\n: new line
\r: carriage return
\': single quotation mark
\": double quotation mark
\\: backslash
\$: dollar sign
- Strings
String은 문자열이며, JVM에서 UTF-16을 사용하기 때문에 문자 하나당 2bytes를 사용한다.
String은 큰따옴표 안에 존재한다.
String은 immutable로 후에 바꿀 수 없기 때문에 새로운 문자열 객체를 만들어서 대입해야 한다.
String은 +를 사용하여 문자열들을 이을 수 있다.
val s = "abc" + 1
println(s + "def")
// abc1def
- Strings
Array는 같은 타입이거나 그것들의 sub 타입 객체들을 고정된 숫자로 가지고 있는 자료구조이다.
Create arrays
코틀린에서 배열을 생성하기 위해서는 다음과 같은 함수들을 사용한다.
arrayOf(), arrayOfNulls(), emptyArray()
arrayOf()는 괄호 안에 value들을 넣어서 생성한다.
// Creates an array with values [1, 2, 3]
val simpleArray = arrayOf(1, 2, 3)
println(simpleArray.joinToString())
// 1, 2, 3
arrayOfNulls를 사용하면 해당 사이즈를 가지는 null 배열을 생성한다.
// Creates an array with values [null, null, null]
val nullArray: Array<Int?> = arrayOfNulls(3)
println(nullArray.joinToString())
// null, null, null
emptyArray는 빈 배열을 생성한다.
Nested arrays
Array도 객체이기 때문에 다른 Array 안에 들어 갈 수 있다.
// Creates a two-dimensional array
val twoDArray = Array(2) { Array<Int>(2) { 0 } }
println(twoDArray.contentDeepToString())
// [[0, 0], [0, 0]]
Access and modify elements
Array는 mutable하기 때문에 수정이 가능하다.
접근 할 때도 []를 사용하여 접근 할 수 있다.
simpleArray[0] = 10
twoDArray[0][0] = 2
Work with arrays
Pass variable number of arguments to a function
코틀린에서는 vararg를 통해, 가변 개수의 parameter를 받을 수 있다.
이런 방법은 사전에 정해지지 않은 수의 파라미터를 받는 경우에 굉장히 유리하다.
이런 vararg를 사용하는 함수에 array를 통해 가변 개수의 parameter를 넘기려면 *을 사용한다.
배열에 있는 각각의 객체를 spread해서 넘겨주는 연산자이다.
fun main() {
val lettersArray = arrayOf("c", "d")
printAllStrings("a", "b", *lettersArray)
// abcd
}
fun printAllStrings(vararg strings: String) {
for (string in strings) {
print(string)
}
}
Compare arrays
두개의 Array가 같은 순서로 같은 객체들을 가지고 있는지 확인하기 위해서는 .contentEquals()를 사용하면 된다.
val simpleArray = arrayOf(1, 2, 3)
val anotherArray = arrayOf(1, 2, 3)
// Compares contents of arrays
println(simpleArray.contentEquals(anotherArray))
// true
// Using infix notation, compares contents of arrays after an element
// is changed
simpleArray[0] = 10
println(simpleArray contentEquals anotherArray)
// false
Transform arrays
코틀린은 array를 transform 하는 것에 많은 함수들을 제공한다.
- Sum
.sum을 사용하여 해당 Array의 element를 모두 더한 값을 리턴한다.
val sumArray = arrayOf(1, 2, 3)
// Sums array elements
println(sumArray.sum())
// 6
- Shuffle
Array에서 해당 elements들을 랜덤하게 섞기 위해서 사용하는 함수이다.
val simpleArray = arrayOf(1, 2, 3)
// Shuffles elements [3, 2, 1]
simpleArray.shuffle()
println(simpleArray.joinToString())
// Shuffles elements again [2, 3, 1]
simpleArray.shuffle()
println(simpleArray.joinToString())
- Convert arrays to collections
Array를 List와 Set으로 변환 할 수 있다.
.toList()와 .toSet()을 사용하면 된다.
val simpleArray = arrayOf("a", "b", "c", "c")
// Converts to a Set
println(simpleArray.toSet())
// [a, b, c]
// Converts to a List
println(simpleArray.toList())
// [a, b, c, c]
- Type checks and casts
is and !is operators
인스턴스가 해당 타입의 객체인지 확인하기 위해서는 is, !is operator를 사용한다.
if (obj is String) {
print(obj.length)
}
if (obj !is String) { // Same as !(obj is String)
print("Not a String")
} else {
print(obj.length)
}
Smart casts
컴파일러는 is, !is로 확인 한 경우에는 안전하게 해당 타입으로 캐스팅을 해준다.
그렇기 때문에 개발자가 직접 타입을 as를 사용하여 변환 할 필요가 없다.
fun demo(x: Any) {
if (x is String) {
print(x.length) // x is automatically cast to String
}
}
if (x !is String) return
print(x.length) // x is automatically cast to String
"Unsafe" cast operator
명시적으로 타입을 캐스팅하고 싶다면 as를 사용한다.
val x: String = y as String
만약 캐스팅이 불가능하다면, Exception이 발생한다.
"Safe" (nullable) cast operator
이런 exception을 피하기 위해서는 as? 연산자를 사용한다.
만약 해당 캐스팅이 실패하면 null이 return 되게 된다.
val x: String? = y as? String