Basic Types
코틀린에서 모든 것은 객체로서 변수에 대한 멤버 함수나 프로퍼티를 호출할 수 있다. 어떤 타입은 특별한 내부 표현을 갖는다 -예를 들어 숫자, 문자, 불리언 같은 타입은 러타임에 기본 값으로 표현된다- 하지만 사용자에게는 일반 클래스처럼 보인다. 이 절에서는 코틀린의 기본 타입인 숫자, 문자, 불리언, 배열, 문자열에 대해 설명한다.
Numbers
코틀린은 자바와 유사한 방법으로 숫자를 다루지만 정확히 일치하진 않는다. 그 예로 숫자에 대해 넓은 타입으로 자동변환이 없고, 어떤경우에는 리터럴도 약간 다르다.
코틀린이 제공하는 숫자 내장타입은 다음과 같다(이는 자바와 유사하다.)
코틀린에서 문자는 숫자가 아니다.
Type | Bit width |
---|---|
Double | 64 |
Float | 32 |
Long | 64 |
Int | 32 |
Short | 16 |
Byte | 8 |
코틀린에서 문자는 숫자가 아니다.
Literal Constants
정수 값을 위한 리터럴 상수 종류는 다음과 같다.
- 10진수 : 123
- Long은 대문자 L로 표시 : 123L
- 16진수 : 0x0F
- 2진수 : 0b00001011
8진수 리터럴은 지원하지 않는다.
또한 부동소수점을 위한 표기법을 지원한다:
- 기본은 Double : 123.5, 123.5e10
- Float은 f나 F로 표시 : 123.5f
Underscores in numeric literals (since 1.1)
1.1부터는 가독성을 위해 상수에 밑줄 사용이 가능하다.
1 2 3 4 5 | val oneMillion = 1_000_000 val creditCardNumber = 1234_5678_9012_3456L val socialSecurityNumber = 999_99_9999L val hexBytes = 0xFF_EC_DE_5E val bytes = 0b11010010_01101001_10010100_10010010 | cs |
Representation
자바 플랫폼에서는 JVM 기본 타입으로 숫자를 내장(physically stored)한다. nullable 숫자 레퍼런스(예 Int? )가 필요하거나 지네릭이 관여하면 박싱(boxing) 타입으로 저장한다.
숫자를 박싱하면 동일성을 보장하지 않는다:
1 2 3 4 5 | val a: Int = 10000 print(a === a) // Prints 'true' val boxedA: Int? = a val anotherBoxedA: Int? = a print(boxedA === anotherBoxedA) // !!!Prints 'false'!!! | cs |
반면에 아래는 동등함을 유지한다.(값 동일)
1 2 3 4 5 | val a: Int = 10000 print(a == a) // Prints 'true' val boxedA: Int? = a val anotherBoxedA: Int? = a print(boxedA == anotherBoxedA) // Prints 'true' | cs |
Explicit Conversions
표현이 다르므로 작은 타입이 큰 타입의 하위 타입은 아니다. 하위 타입이 된다면 다음과 같은 문제가 발생한다:
1 2 3 4 | // 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(a == b) // Surprise! This prints "false" as Long's equals() check for other part to be Long as well | cs |
동일성뿐만 아니라 동등함조차 모든 곳에서 알아차리지 못하고 사라지게 된다.
이런 이유로 작은 타입을 큰 타입으로 자동으로 변환하지 않는다. 이는 명시적 변환없이 Byte 타입 값을 Int 변수에 할당할 수 없음을 뜻한다.
1 2 | val b: Byte = 1 // OK, literals are checked statically val i: Int = b // ERROR | cs |
명시적으로 숫자를 넓히는 변환을 할 수 있다
1 | val i: Int = b.toInt() // OK: explicitly widened | cs |
모든 숫자 타입은 다음의 변환을 지원한다.
- toByte() : Byte
- toShort() : Short
- toInt() : Int
- toLong() : Long
- toFloat() : Float
- toDouble() : Double
- toChar() : Char
자동 변환의 부재를 거의 느낄 수 없는데 이유는 타입을 컨텍스트에서 추론하고 수치 연산을 변환에 알맞게 오버로딩했기 때문이다. 다음은 예이다
1 | val l = 1L + 3 // Long + Int => Long | cs |
Operations
코틀린은 숫자에 대한 표준 수치 연산을 지원한다. 이들 연산은 알맞은 클래스의 멤버로 선언되어 있다. (하지만 컴파일러는 메서드 호출을 대응하는 명령어로 최적화한다.) 연산자 오버로딩 을 참고하자.
비트 연산자를 위한 특수 문자는 없고 중의 형식으로 호출할 수 있는 함수를 제공한다. 다음은 예이다:
1 | val x = (1 shl 2) and 0x000FF000 | cs |
다음은 전체 비트 연산자 목록이다( Int 와 Long 에서만 사용 가능):
- shl(bits) - 부호있는 왼쪽 시프트 (자바의 <<)
- shr(bits) - 부호있는 오른쪽 시프트 (자바의 >>)
- ushr(bits) - 부호없는 오른쪽 시프트 (자바의 >>>)
- and(bits) - 비트의 AND
- or(bits) - 비트의 OR
- xor(bits) - 비트의 XOR
- inv() - 비트의 역
Floating Point Numbers Comparison
이 섹션에서는 부동소수의 연산을 설명한다.
- 동등함 비교 : a == b and a != b
- 비교 연산자 : a < b, a > b, a <= b, a >= b
- 범의 예시와 검사 : a..b, x in a..b, x !in a..b
피연산자 a 와 b 가 정적으로 Float 나 Double 이거나 또는 이에 해당하는 null 가능 타입일 때(타입을 선언하거나 추정하거나 또는 스마트 변환 의 결과), 숫자나 범위에 대한 연산은 부동소수 연산에 대한 IEEE 754 표준을 따른다.
하지만 범용적인 용례를 지원하고 완전한 순서를 제공하기 위해, 피연산자가 정적으로 부동소수점 타입이 아니면(예 Any , Comparable<...> , 타입 파라미터) 연산은 Float 과 Double 을 위한 equals 와 compareTo 구현을 사용한다. 이는 표준과 비교해 다음이 다르다.
- NaN은 자신과 동일하다고 간주한다.
- NaN은 POSITIVE_INFINITY를 포함한 모든 다른 요소보다 크다고 간주한다.
- -0.0은 0.0보다 작다고 간주한다.
Characters
문자는 Char타입으로 표현한다. 이 타입을 바로 숫자로 다룰 수 없다
1 2 3 4 5 | fun check(c: Char) { if (c == 1) { // ERROR: incompatible types // ... } } | cs |
문자 리터럴은 작은 따옴표 안에 표시한다 : '1' . 특수 문자를 역슬래시로 표시한다. 다음 특수문자를 지원한다 : \t, \b, \n, \r, \', \", \\, \$. 임의의 문자를 인코딩하려면 유니코드 표기법을 사용한다 : '\uFF00'.
문자를 Int 숫자로 명시적으로 변환할 수 있다:
1 2 3 4 5 | fun decimalDigitValue(c: Char): Int { if (c !in '0'..'9') throw IllegalArgumentException("Out of range") return c.toInt() - '0'.toInt() // Explicit conversions to numbers } | cs |
숫자와 마찬가지로, 문자도 null 가능 레퍼런스가 필요하면 박싱된다. 박싱 연산을 하면 동일성은 유지되지 않는다.
Booleans
Boolean 타입은 불리언을 표현하고 두 값이 존재한다 : true 와 false .
null 가능 레퍼런스가 필요하면 불리언도 박싱된다.
불리언에 대한 내장 연산에는 다음이 있다.
- || - 지연 논리합
- && - 지연 논리곱
- ! - 부정
Arrays
코틀리은 Array클래스로 배열을 표현하며, 이 클래스는 get 과 set 함수(연산자 오버로딩 관례에 따라 [] 로 바뀜), size 프로퍼티와 그외 유용한 멤버 함수를 제공한다:
1 2 3 4 5 6 7 8 | class Array<T> private constructor() { val size: Int operator fun get(index: Int): T operator fun set(index: Int, value: T): Unit operator fun iterator(): Iterator<T> // ... } | cs |
라이브러리 함수 arrayOf() 를 사용해서 배열을 생성할 수 있다. 이 함수에는 항목 값을 전달하는데 arrayOf(1, 2, 3) 은 [1, 2, 3] 배열을 생성한다. arrayOfNulls() 라이브러리 함수를 사용하면 주어진 크기의 null로 채운 배열을 생성할 수 있다.
배열을 생성하는 다른 방법은 팩토리 함수를 사용하는 것이다. 팩토리 함수는 배열 크기와 해당 인덱스에 위치한 요소의 초기값을 리턴하는 함수를 인자로 받는다:
1 2 | // Creates an Array<String> with values ["0", "1", "4", "9", "16"] val asc = Array(5, { i -> (i * i).toString() }) | cs |
앞서 말했듯이, [] 연산자는 get() 과 set() 멤버 함수 호출을 의미한다.
공지: 자바와 달리 코틀린 배열은 불변식이다. 이는 코틀린은 Array<String>을 Array<Any>에 할당할 수 없음을 의미하며, 런타임 실패를 방지한다. (하지만 Array<out Any>을 사용할 수 있다. 타입 프로젝션을 참고하자.)
1 2 | val x: IntArray = intArrayOf(1, 2, 3) x[0] = x[1] + x[2] | cs |
Strings
문자열은 String타입으로 표현한다. 문자열은 불변이다. 문자열의 요소는 문자로서 s[i] 와 같은 인덱스 연산으로 접근할 수 있다. for -루프로 문자열을 순회할 수 있다:
1 2 3 | for (c in str) { println(c) } | cs |
String Literals
코틀린은 두 가지 타입의 문자열 리터럴을 지원한다. 하나는 escaped 문자열로 탈출 문자를 가질 수 있다. 다른 하나는 raw 문자열로 뉴라인과 임의 텍스트를 가질 수 있 다. escaped 문자열은 자바 문자열과 거의 같다:
1 | val s = "Hello, world!\n" | cs |
특수 문자는 전형적인 방식인 역슬래시를 사용한다. 지원하는 특수 문자 목록은 앞서 문자 를 참고한다. raw 문자열은 세 개의 따옴표로 구분하며( """ ), 특수 문자를 포함하지 않고 뉴라인과 모든 다른 문자를 포함할 수 있다:
1 2 3 4 | val text = """ for (c in "foo") print(c) """ | cs |
trimMargin() 함수를 사용해서 앞쪽 공백을 제거할 수 있다:
1 2 3 4 5 6 | val text = """ |Tell me and I forget. |Teach me and I remember. |Involve me and I learn. |(Benjamin Franklin) """.trimMargin() | cs |
기본으로 | 를 경계 접두문자로 사용하지만 trimMargin(">") 과 같이 파라미터를 이용해서 다른 문자를 경계 문자로 사용할 수 있다.
String Templates
문자열은 템플릿 식을 포함할 수 있다. 예를 들어, 코드 조각을 계산하고 그 결과를 문자열에 넣을 수 있다. 템플릿 식은 달러 부호($)로 시작하고 간단한 이름으로 구성된다
1 2 | val i = 10 val s = "i = $i" // evaluates to "i = 10" | cs |
또는 중괄호 안에 임의의 식을 넣을 수 있다:
1 2 | val s = "abc" val str = "$s.length is ${s.length}" // evaluates to "abc.length is 3" | cs |
raw 문자열과 escaped 문자열 안에 템플릿을 넣을 수 있다. 역슬래시 특수 문자를 지원하지 않는 raw 문자열에서 $ 문자를 표현하고 싶다면 다음 구문을 사용한다:
1 2 3 | val price = """ ${'$'}9.99 """ | cs |
0 개의 댓글:
Post a Comment