[Kotlin] - 코틀린에서 변수를 다루는 방법
자바 개발자를 위한 코틀린 입문을 공부하며 작성한 글입니다.
혼자 공부하고 정리한 내용이며, 틀린 부분은 지적해주시면 감사드리겠습니다 😀
var VS val
모든 변수는 우선
val
로 만들고, 꼭 필요한 경우var
로 변경한다.
long number1 = 10L;
final long number2 = 10L;
long
과 final long
의 차이는 가변 / 불변의 차이를 나타낸다.
구분 | 설명 |
---|---|
long |
처음 값을 할당 받고 나서, 다시 한 번 값을 바꿔줄 수 있다. |
final long |
한 번 값을 지정해주면 더 이상 바꿀 수 없다. |
위 코드를 코틀린으로 변환하면 다음과 같다.
// variable
var number1 = 10L
// value
val number2 = 10L
코틀린에서는 모든 변수에 수정 가능 여부를 명시해주어야 하며, 타입은 컴파일러가 추론해주기 때문에 의무적으로 작성하지 않아도 된다.
늦은 초기화
var number1: Long
val number2: Long
// 에러 발생 : Variable 'number1' must be initialized
// print(number1)
// print(number2)
number1 = 5
number2 = 5
print(number1)
print(number2)
var
과 val
모두 값이 초기화되지 않은 상태에서 출력을 하려고 하면 에러가 발생한다.
val
은 최초 한 번에 한해서 값을 초기화할 수 있다.
초기값을 지정해주지 않을 경우 타입을 무조건 명시해줘야 하며, 값을 초기화한 후 사용해야한다.
Primitive Type
java
에는 Reference
와 Primitive
타입이 모두 존재한다.
long number1 = 10L
Long number3 = 1_000L;
Effective Java, Item6을 보면 다음과 같은 내용이 존재한다.
연산을 할 때에는, 박싱된 기본 타입보다는 기본 타입을 사용하고, 의도치 않은 오토 박싱이 숨어들지 않도록 주의하자.
private static long sum() {
Long sum = 0L;
for (long i = 0; i <= Integer.MAX_VALUE; i++) {
sum += i;
}
return sum;
}
위 코드의 경우 Long
타입이 long
과 연산을 하는 과정에서 박싱과 언박싱이 계속해서 일어나 불필요한 객체가 생성이 되면서 성능이 저하된다.
하지만, 코틀린의 경우 동일하게 사용한다.
var number1 = 10L
var number3 = 1_000L
공식 문서를 보면 다음과 같은 내용이 있는 것을 볼 수 있다.
Some types can have a special internal representation
- for example, numbers, characters and booleans
- can be represented as primitive values at runtime
- but to the user they look like ordinary classes.
코드에서는 평범한 클래스처럼 보이지만, 실행 시에는 코틀린이 알아서 최적화를 해준다.
실제로 작성한 코드를 디컴파일 해보면 다음과 같다.
fun main() {
var result: Long = 0L
for (i in 0L .. 10L) {
result += (i + 1L)
}
println(result)
}
public final class KotlinVariableKt {
public static final void main() {
long number1 = 0L;
long result = 0L;
long i = 0L;
for(long var6 = 10L; i <= var6; ++i) {
result += i + 1L;
}
System.out.println(result);
}
public static void main(String[] var0) {
main();
}
}
분명 kotlin
에서는 Long
타입으로 작성했지만, 실제 디컴파일된 코드를 보면 primitive long
으로 작성된 것을 볼 수 있다.
이처럼 프로그래머가 boxing / unboxing을 고려하지 않아도 되도록 kotlin
이 알아서 처리해준다.
nullable
java
에서 Reference
타입으로 작성하면 null
을 허용할 수 있게 된다.
Long nubmer = null;
하지만 kotlin
에서는 ‘null이 들어갈 수 있는’을 아예 다르게 간주한다.
var number = 1_000L
// 에러 발생 : Null can not be a value of a non-null type Long
number = null
기본적으로 모든 변수는 null
이 들어갈 수 없게끔 설계되었기 때문에 에러가 발생하는 것이다.
그렇기 때문에 null
을 허용할 수 있도록 타입에 ?
를 명시해주어야 한다.
var number: Long? = 1_000L
number = null
Instance
java
에서 객체를 생성하기 위해서는 아래와 같이 new
키워드를 사용해야 한다.
Person p = new Person("Jwhy")
kotlin
의 경우 해당 키워드 없이 바로 사용이 가능하다.
var person = Person("Jwhy")
위와 같이 객체 인스턴스화를 할 때에는 new
를 붙이지 않는다.
정리
- 모든 변수는 var / val을 붙어주어야 한다.
- var : 변경 가능
- val : 변경 불가능 (read-only)
- 타입을 명시하지 않아도, 추론이 가능하다.
-
Primitive
와Reference
타입을 구분하지 않아도 된다. -
null
이 들어갈 수 있는 변수는 타입 뒤에?
를 붙어주어야 한다.- 아예 다른 타입으로 간주한다.(Long != Long?)
- 객체를 인스턴스화 할 때,
new
를 붙이지 않아야 한다.
댓글남기기