Java에서는 Primitive type 은 직접 숫자 리터럴을 가지고 있는 변수가 되었다. 하지만 kotlin 에서는 숫자조차도 Object 이다. 따라서 Int, Long 의 변수조차도 참조값을 갖는 형태이다.
코틀린에서는 var와 val 을 이용해서 변수를 선언할 수 있다. var 는 값을 변화시킬 수 있는, val 는 값을 변화시킬 수 없는 변수라고 쓰여있다. 하지만 더 정확하게 말하자면 val 는 변수가 참조하고 있는 참조값(주소값)을 바꿀 수 없는 변수를 말하는 것이다.여기서 주의할 점은 만약 참조값 자체를 바꾸는게 아니라 참조하고 있는 객체를 업데이트 하는 메서드를 이용하면, 당연히 참조하고 있는 객체가 담고 있는 객체의 속성을 바꿀 수 있다는 점이다.
모든 숫자형 자료는 초기화할 때 자료형을 지정하지 않으면, Int로 인식되며, Int 형의 자료범위를 벗어나거나 뒤에 L을 붙이면 Long 으로 인식된다.
IEEE 754 standard 표준에 맞춰 Floating Point 방식으로 실수를 표현한다.
실수형 자료는 초기화 시 Double 로 인식되며, Float 형으로 하기 위해서는 뒤에 F 를 붙여줘야한다. 다른 언어와는 다르게 실수형 자료는 암묵적인 형변환을 지원하지 않다. Double 형이 필요한 곳에는 무조건 Double 형이 들어가야 한다.
16진수, 2진수 등을 표현할때는 아래와 같이 표현한다.
JVM 플랫폼에서 숫자는 int, double 과 같은 primitive type 에 저장된다. 하지만 nullable number 참조자, 제네릭 같은 경우는 Java Integer, Double Class에 감싸져서 저장이 된다.
Kotlin 은 암묵적인 형변환을 지원하지 않는다. 즉, 더 작은 자료형은 큰 자료형에 서브 자료형이 아니라는 것이다. 이는 위에서 설명한 JVM의 숫자표현 때문인데,
val a: Int? = 1 // Integer Class 로 저장.
val b: Long? = a // 암묵적인 형변환, Long Class 로 저장.
print (b == a) // equality 검사 : false
nullable과 제네릭은 java class 로 저장되므로, 암묵적 형변환이 있으면 객체 자체가 변화하는 일이 발생하고, equality 와 identity 검사가 의미를 잃게 된다.
이러한 문제로 kotlin 에서는 암묵적 형변환은 지원되지 않는다. 명시적 형변환을 무조건 해줘야한다.
기본적인 산술 연산자는 일반적인 언어와 동일하다.
비트 연산자는 c 의 >>, << 와는 많이 다르다.
||, &&, ! 연산은 똑같다. Boolean? 이 nullable 인것이 다르다.
Char 자료형으로 표현된다. `` 를 이용해서 표현된다.
String 자료형으로 표현되고, "" 를 이용해서 표현된다. String Template 라고 해서 C 의 printf 와 같이 사용되는 용법이 있는데,
$ 표시를 이용해서 변수를 참조하고, $ 를 String 에서 표현하기 위해서는 맨 마지막과 같이 이용한다.
Array 클래스는 get, set 함수를 가지고 있다. 가령 이런 식이다.
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>
// ...
}
Array 를 만들기 위해서는 arrayOf() 함수나 arrayOfNulls() 함수를 이용할 수 있다.
kotlin 자료형에서 암묵적인 형변환을 지원하지 않으므로 명시적 형변환을 써야한다고 말했다. 하지만 is 체크가 있는 경우
컴파일러가 형변환자를 삽입하므로 굳이 개발자가 형변환자를 삽입할 필요가 없다.
fun demo(x: Any) {
if (x is String) {
// val str = x as String
// print(str.length)
print(x.length) // Smart cast 로 위의 형변환 작업이 필요없음
}
}
위 코드에서 x 는 Any 타입으로 어떤 자료형도 올 수 있다. 따라서 if 이하의 x.length 를 실행하려면 val str = x as String
이런 명시적 형변환이 있어야 할 것 같지만, 컴파일러는 이미 if (x is String)
구문에서 x 가 String 형이라는 것을 확인 했으므로 굳이 개바랒가 명시적으로 형변환을 해줄 필요없다는 것이다.